2016-04-20 2 views
1

Если у меня есть иерархия классов C++, где базовый класс имеет функцию-член, объявленную как виртуальную, но производные классы не объявляют эту функцию виртуальной, как далеко в иерархии классов виртуализация несут. Например, данный код является корректным значением возвращаемого значения MyFunc2?Правила получения не виртуального потомка с виртуальным базовым классом

class A 
{ 
public: 
    virtual int x() { return 1; } 
} 

class B : public A 
{ 
public: 
    int x() { return 2; } 
}; 

class C: public B 
{ 
public: 
    int x() { return 3; } 
}; 

int MyFunc1(f &A) 
{ 
return f.x(); 
} 

int MyFunc2(f &B) 
{ 
return f.x(); 
} 

int MyFunc3() 
{ 
C c; 
return MyFunc1(c); 
} 

int MyFunc4() 
{ 
C c; 
return MyFunc2(c); 
} 

От similar question here, казалось бы, что виртуальная характеристика распространяется вперед для всех классов, как только это виртуальная в базовом классе, но мне интересно, насколько хорошо определены это, в частности, является Bx() виртуальный по подразумевается вывод из A.

ответ

4

Переопределения в подклассах также неявно являются виртуальными. Вы можете снова задать ключевое слово virtual, но это не имеет никакого значения, хотя часто считается хорошей практикой. Он абсолютно «четко определен» в стандарте.

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

1

Да, атрибут virtual «размножается» (чтобы использовать вашу формулировку) для всех производных классов. Если производные классы объявляют и определяют функцию-член с той же сигнатурой, что и унаследованная виртуальная функция, они переопределяют ее.

В C++ 11 был внесен модификатор final, который производные классы могут использовать для предотвращения их потомков от дальнейшего переопределения унаследованной виртуальной функции. Однако функция по-прежнему технически виртуальна (например, с учетом указателя на базу, полиморфный вызов p->func() вызывает func(), соответствующий фактическому типу объекта) .... он просто не может быть переопределен.

+0

Что означает «технический»? В каком другом смысле есть конечная функция * не * виртуальная? –

+0

Слово «технически» означает «имеет характеристики, связанные с ним ...» – Peter

+0

Да, но это просто действительно запутанный способ сказать «есть» :-) –

Смежные вопросы