2017-02-12 13 views
1

У меня есть этот простой код, чтобы проверить VFВиртуальные функции Сомнения

class A 
{ 
public: 
virtual const char Get(){return 'A';} 
}; 

class B : public A 
{ 
public: 
const char Get(){return 'B';} 
}; 

class C : public B 
{ 
public: 
const char Get(){return 'C';} 
}; 

class D : public C 
{ 
public: 
const char Get(){return 'D';} 
}; 

внутри основных()

D dD; 
std::cout<<dD.Get()<<std::endl; //prints D 

A & rA = dD; 
std::cout<<rA.Get()<<std::endl;//prints D 

C cC; 

A & rA2 = cC; 
std::cout<<rA2.Get()<<std::endl; //print C 

B & rB = dD; 
std::cout<<rB.Get()<<std::endl; 
/*????? it prints D, shouldn't it print B ?????*/ 

Р.Б. точек для решения Д.Д., гв будет относиться только к объекту (В и А) объекта dD (не будет видеть C & D).

Когда вызывается rB.Get(), не следует ли ему перейти к самой производной функции, которая находится в B, а не в A и выполнить ее?

+1

Почему, по вашему мнению, самый производный объект находится в B? rB является ссылкой на B, но наиболее выведенным является D. См .: http://en.cppreference.com/w/cpp/language/virtual – doug

+0

хорошо исправьте меня, если я ошибаюсь, но я подумал в случае rB это относится к части A и B объекта dD, и в этом контексте, когда вызывается rB.Get(), компилятор увидит наиболее производный Get() в A & B, и это B :: Get() – Forat

+1

@Adam : Да, вы ошибаетесь. 'rB' является ссылкой на объект' D'. Весь смысл «виртуальных» функций состоит в том, что статический тип может быть базовым, тогда как динамический тип является производным, а для «виртуальной» функции выдается наиболее производный динамический тип. –

ответ

1

Когда функция виртуальна в классе Base, она является виртуальной во всех производных классах, классах, производных от производных классов и т. Д., Независимо от использования или отсутствия слова virtual в производных классах.

В вашем случае это означает, что Get является виртуальным во всех классах A, B, C и D. Следовательно, примеры rA и rB являются примерами такой же ситуации.

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

+0

да виртуальная база сделает производные функции виртуальными тоже, эта часть меня смутила, но теперь я ее понял. спасибо – Forat