Базовый указатель всегда указывает на базовую часть производного объекта.Он не знает никакой информации о членах / методах производных объектов.
Если вы объявите метод A::disp()
как virtual
, то только он будет разрешен во время выполнения.Он может вызвать A::disp()
или B::disp()
в зависимости от объекта, на который указывает a_ptr
.
Простыми словами:
- Если вы объявите метод
virtual
, то компилятор знает,что этот метод должен быть оценен во время выполнения.Кроме того, метод должен вызываться с использованием указателя или ссылки. - Если метод вызывается с использованием объекта или метод не
virtual
, то компилятор сразу же вызывает метод статического типавызывающий абонент.
В вашем случае статический тип вызывающего абонента - A*
, а метод - не virtual
.Таким образом, компилятор сразу отправил вызов для A::disp()
;он не ожидает оценки во время выполнения.
a_ptr = &b_obj; // static type --> typeof(*a_ptr) --> A
// dynamic type --> typeof(b_obj) --> B
a_ptr->disp(); // (is A::disp() virtual)?
// chooses B::disp() at runtime : chooses A::disp() at compiletime;
[Примечание: предположим, что если вы сделаете только B::disp()
в качестве virtual
и сохраните A::disp()
обычным методом, то все равно получитете же результаты, что и сейчас.]