Виртуальная функция в иерархии наследования

Когда у меня что-то подобное, и когда у меня есть 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 (обратите внимание, что любая виртуальная функция в базовом классе продолжает оставаться виртуальной в производном классе).

Другие вопросы по тегам