Как производный объект в базовом указателе вызывает базовую функцию? - PullRequest
1 голос
/ 21 июля 2011

Как базовый указатель, содержащий производный объект, все еще может указывать на базовую функцию? Здесь после

a_ptr = &b_obj; 
a_ptr->disp();

Если базовая функция была виртуальной, я понимаю использование V-таблицы, которая содержит адрес базовой функции. Но здесь объект, производный от базового указателя, может вызывать базовую функцию.

Может кто-нибудь пролить свет на то, что происходит за сценой?

class A
{
 public:
 //virtual void disp()
 void disp()
 { cout<< "From class A\n" << endl; }
};

class B : public A
{
public:
 void disp()
 { cout << "From Class B\n" <<endl; }
};

int main()
{
 A a_obj;
 A *a_ptr;

 B b_obj;

 a_ptr = &a_obj;
 a_ptr->disp();

 a_ptr = &b_obj;
 a_ptr->disp();
}

1 Ответ

5 голосов
/ 21 июля 2011

Базовый указатель всегда указывает на базовую часть производного объекта.Он не знает никакой информации о членах / методах производных объектов.

Если вы объявите метод A::disp() как virtual, то только он будет разрешен во время выполнения.Он может вызвать A::disp() или B::disp() в зависимости от объекта, на который указывает a_ptr.

Простыми словами:

  1. Если вы объявите метод virtual, то компилятор знает,что этот метод должен быть оценен во время выполнения.Кроме того, метод должен вызываться с использованием указателя или ссылки.
  2. Если метод вызывается с использованием объекта или метод не 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() обычным методом, то все равно получитете же результаты, что и сейчас.]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...