С virtual
:
class Base {
virtual void Foo() { std::cout << "Foo in Base" << std::endl;}
};
class Derived : public Base {
virtual void Foo() { std::cout << "Foo in Derived" << std::endl;}
};
// in main()
Derived* d = new Derived();
d->Foo(); // prints "Foo in Derived"
Base* b = new Derived();
b->Foo(); // prints "Foo in Derived"
и без (тот же код, но пропустите virtual
):
// in main()
Derived* d = new Derived();
d->Foo(); // prints "Foo in Derived"
Base* b = new Derived();
b->Foo(); // prints "Foo in Base"
так что разница в том, что без virtual
нет истинного полиморфизма времени выполнения: какая функция вызывается, определяется компилятором в зависимости от текущего типа указателя / ссылки, через которую она вызывается.
С помощью virtual
объекты поддерживают список виртуальных функций (vtable
), в котором он ищет фактический адрес вызываемой функции - во время выполнения, каждый раз, когда вы вызываете виртуальный член этой функции. В этом примере запись для Foo
неявно модифицируется конструктором Derived
, чтобы указывать на переопределенную функцию, поэтому не имеет значения, что Foo
вызывается через Base
-точку.