В C ++ является ли функция автоматически виртуальной, если она переопределяет виртуальную функцию?

StackOverflow https://stackoverflow.com/questions/1404797

  •  05-07-2019
  •  | 
  •  

Вопрос

Я бы ожидал, что если foo объявлен в классе D, но не помеченный как virtual, тогда следующий код вызовет реализацию foo в D (независимо от динамического типа d).

D& d = ...;
d.foo();

Однако в следующей программе это не так.Кто-нибудь может это объяснить?Является ли метод автоматически виртуальным, если он переопределяет виртуальную функцию?

#include <iostream>

using namespace std;

class C {
public:
        virtual void foo() { cout << "C" << endl; }
};

class D : public C {
public:
        void foo() { cout << "D" << endl; }
};

class E : public D {
public:
        void foo() { cout << "E" << endl; }
};

int main(int argc, char **argv)
{
        E& e = *new E;
        D& d = *static_cast<D*>(&e);
        d.foo();
        return 0;
}

Результатом работы приведенной выше программы является:

E
Это было полезно?

Решение

Стандарт 10.3.2 (class.virtual) гласит:

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

[Сноска:Функция с тем же именем, но с другим списком параметров (предложение over) в качестве виртуальной функции не обязательно является виртуальной и не переопределяется.Использование виртуального спецификатора при объявлении переопределяющей функции является законным, но избыточным (имеет пустую семантику).Управление доступом (предложение class.access) не учитывается при определении переопределения.--- конец заметки]

Другие советы

Быстрого ответа может быть нет, но правильный ответ - да

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

Вы не создаете копию объекта e и не помещаете ее в d. Таким образом, d.foo () следует нормальному полиморфному поведению и вызывает метод производного класса. Метод, объявленный как виртуальный в базовом классе, автоматически становится виртуальным в производном классе.

Вывод (" E ") ведет себя точно так, как можно было бы ожидать.

Причина: Динамический (т. Е. Во время выполнения) тип этой ссылки - E. Вы выполняете статическое преобразование в D, но это, конечно, не меняет фактический тип объекта.

В этом и заключается идея виртуальных методов и динамических распределений: вы видите поведение того типа, для которого вы создали экземпляр, в данном случае это E.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top