Как vptr и vtable работают в приведенном ниже виртуальном коде?

Насколько я знаю, когда мы делаем виртуальную функцию в базовом классе, указатель, на который можно ссылаться как vptr, создается компилятором, а vtable содержит записи виртуальной функции, которые являются последней версией для этого класса в случае переопределенной функции. и vptr указывает на vtable. классы, производные от базового класса, имеют ту же историю, они имеют указатель vptr и собственную vtable, которая содержит записи последней виртуальной функции. Чтобы понять мой вопрос, следуйте коду

#include <iostream>
using namespace std;
class base
{
public:
virtual void display(void)
{
    cout << "base\n";
}
};

class derived : public base
{
public:
void display(void)
{
    cout << "derived\n";
}
};
int main(void)
{
    base *p;
    base ob1;
    derived ob2;
    p=&ob2;
    p->display();//my point starts from here
    p->base::display();

}

В приведенном выше коде оператор p->display(); имеет смысл, что точки объекта p вызывают vptr этого класса и ищут функцию отображения в таблице vtable и связывают ее. Но я не понимаю, как бы я описал оператор p->base::display(); с точки зрения vptr и vtable. Как компилятор свяжет функцию отображения версии базового класса. Поскольку в vtable производного класса не будет функции отображения версии базового класса. Если что-то из того, что я знаю, здесь неправильно, пожалуйста, скажите мне, что правильно. И если я прав, то скажите мне, как я буду описывать p->base::display(); оператор с логикой, которую я описал p->display(); утверждение


person Community    schedule 16.07.2019    source источник


Ответы (1)


Но я не понимаю, как бы я описал оператор p->base::display(); с точки зрения vptr и vtable. как компилятор свяжет функцию отображения версии базового класса

Vptr никак не участвует в этом вызове. Vptr используется только в виртуальной диспетчеризации.

Использование явного разрешения области действия в этом вызове означает, что вы используете статическую диспетчеризацию. Вы говорите, вызовите функцию base::display независимо от динамического типа аргумента объекта.


Виртуальная диспетчеризация — это форма полиморфизма времени выполнения и ключевая особенность объектно-ориентированного программирования. Когда вызов функции отправляется виртуально, он направляется наиболее производному переопределению функции в иерархии наследования, которая зависит от динамического типа объекта.

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

Виртуальная диспетчеризация может использоваться только с виртуальными функциями. Виртуальная диспетчеризация обычно реализуется с использованием таблицы виртуальных функций (vtable) и указателя виртуальных функций (vptr).

person eerorika    schedule 16.07.2019
comment
спасибо за ваш ценный комментарий. Было бы здорово, если бы вы описали что-то о виртуальной отправке и статической отправке, или вы могли бы предложить мне несколько ссылок, чтобы я мог получить четкий ответ на свой вопрос. - person ; 16.07.2019
comment
@S.M.TusharIbneSalam Я добавил объяснение того, что означают виртуальная и статическая диспетчеризация. Что касается ссылок, это должно быть полезно для основ C++: руководство и список книг"> stackoverflow.com/questions/388242/ - person eerorika; 16.07.2019
comment
Я думаю, что виртуальная отправка и позднее/динамическое связывание относятся к одному и тому же. На самом деле я не был знаком со словом виртуальная диспетчеризация. Но слышал о позднем связывании. В конце концов, ваш новый ответ дал мне лучшее решение моего вопроса. Теперь мне кажется, что я правильно понимаю этот вопрос. - person ; 17.07.2019