Виртуальная функция в иерархии наследования
Когда у меня что-то подобное, и когда у меня есть a* mya=new c();
и я звоню a->displayStuff
это вызывает Class a
метод и когда virtual
в Class a
вместо Class b
это вызывает Class b
метод.
поскольку Class c
не имеет реализации этого метода, какое правило применяется здесь?
class a
{
public:
void displayStuff() {}
//other methods
};
class b:public a
{
public:
virtual void displayStuff() {}
//other methods
};
class c:public b
{
//other methods
};
2 ответа
В первом случае у вашего класса A нет виртуальной функции. Поэтому будет вызываться его не виртуальная функция displayStuff. во втором случае, когда вы добавили виртуальный спецификатор функции к функции в классе A, соответствующая функция класса B переопределяет эту функцию. Таким образом, во втором случае вызывается функция класса B, потому что таблица указателей виртуальных функций содержит указатель на функцию, определенную в классе B.
Так как класс c не имеет реализации этого метода, какое правило применяется здесь?
Правило наследования применяется. В зависимости от видимости унаследованного члена и типа наследования члены, видимые в классе B, будут видны в классе C. В этом случае, так как вы наследуете публично, все открытые члены будут видны публично. Таким образом, общедоступная виртуальная функция-член в классе B будет видна как общедоступная виртуальная функция в классе C.
Точно, но когда использовать что и почему, когда у меня несколько уровней наследования?
Это дизайнерское решение. Помните, что не виртуальная функция-член связана во время компиляции, поэтому любой вызов функции через базовый указатель не может быть разрешен, пока вы не собираетесь вызывать функцию. Рассмотрим сценарий
Base
public: foo
/ \
/ \
/ \
/ \
/ \
Derived1 Derived2
public: foo public: foo
Base *p;
std::cin>>cond;
if (cond)
p = new Derived1();
else
p = new Derived1();
p->foo();
В приведенном выше коде решение о вызове foo() (Derived1::foo или Derived2::foo) зависит от некоторых внешних условий, которые не могут быть определены во время выполнения. Единственный способ сделать это возможным - создать виртуальную таблицу, которую можно принудительно создать, только если мы сделаем хотя бы одну функцию в классе virtual (обратите внимание, что любая виртуальная функция в базовом классе продолжает оставаться виртуальной в производном классе).