Предположим, у меня есть следующий код

class base
{
    public:
    virtual void MyVirtual() { std::cout << "This is base MyVirtual \n";}
    void NonVirtual()        { std::cout << "This is base NonVirtual \n";}
};

class derA : public base
{
    public:
    void MyVirtual()  { std::cout << "This is derA MyVirtual \n";}
    void NonVirtual() { std::cout << "This is derA NonVirtual \n";}
};


class derB : public derA
{
    public:
    void MyVirtual()  { std::cout << "This is derB MyVirtual \n";}
    void NonVirtual() { std::cout << "This is derB NonVirtual \n";}
};

int main()
{
    derA *da = new derB;
    da->MyVirtual();     // "This is derB MyVirtual \n"
    da->NonVirtual();
    std::cin.get();
    return 0;
}

Теперь мой вопрос: почему MyVirtual Method ведет себя как виртуальный, если он не отмечен как виртуальный в классе derA?

0
Rajeshwar 28 Мар 2014 в 08:19

2 ответа

Лучший ответ

В C ++ унаследованные виртуальные функции остаются виртуальными в производном классе даже без ключевого слова virtual. Считается хорошей практикой писать virtual для каждой унаследованной функции.

Обновить

Как указано в комментариях к C ++ 11, считается хорошей практикой включать ключевое слово override сразу после декларатора. Это выявляет общий класс ошибок и явно проясняет намерение в коде.

3
Peter R 28 Мар 2014 в 08:30
ПРИМЕЧАНИЕ: в С++ 11 вы должны использовать override
 – 
Bryan Chen
28 Мар 2014 в 08:25
ДерБ б; б.Мой Виртуальный(); Теперь вы вызываете метод класса dderB, при создании объекта полиморфизм не играет своей роли :)
 – 
Ali Kazmi
28 Мар 2014 в 08:28
1
Я не слежу за тобой. Ваш пример ведет себя правильно. Когда вы пишете A a = new B;, вы получаете доступ к методу MyVirtual B через a (это стандартный полиморфизм). И когда вы пишете B b; b.MyVirtual(), наследования нет, и вы все равно получаете поведение B.
 – 
Peter R
28 Мар 2014 в 08:36
Полифоризм достигается за счет использования указателя базового класса, указывающего на объект производного, это привязывается динамически, но когда вы создаете объект, такой как A a;, a создается статически и, следовательно, не может вызывать методы базы:)
 – 
Ali Kazmi
28 Мар 2014 в 10:06

Согласно Стандарту § 10.3 Пункт № 2

Если виртуальная функция-член vf объявлена ​​в классе Base и в классе Derived, производном прямо или косвенно от Base, функция-член vf с тем же именем, параметром-тип-списком, cv-квалификацией и refqualifier (или отсутствием то же самое), поскольку объявлен Base :: vf, то Derived :: vf также является виртуальным (независимо от того, объявлен ли он таким образом) и переопределяет Base :: vf.

Вот ваш ответ, прямо из стандартов. Таким образом, не имеет значения, использовали ли вы ключевое слово virtual в производном классе или нет.

3
Abhineet 28 Мар 2014 в 09:05