Если у вас есть хотя бы одна функция virtual
в классе, то компилятор создает отдельную таблицу для класса с перечислением указателей на функции-члены. Рассмотрим:
struct Base
{
virtual ~Base() { };
int n_;
};
В псевдокод вы можете себе представить, что компилятор добавляет:
void* Base::__virtual_dispatch_table[] = { (void*)&Base::~Base };
Затем, когда у вас есть реальный объект типа Base
будет иметь дополнительный скрытый элемент данных, который указывает к Base::__virtual_dispatch_table
(далее "ВДТ"):
Variable definition Memory layout
------------------- -------------
Base myBase; int n_;
void** __p_vdt = Base::__virtual_dispatch_table;
Теперь, если у вас есть Base* p
и delete p;
, компилятор говорит «эй - это virtual
- Я не буду жёстко вызов Base::~Base
, вместо этого я генерировать код, который делает что-то вроде этого псевдокода:
void (Base::*p_destructor) = p->__p_vdt[0]
*p_destructor(p); // "p" will provide the "this" value while the destructor runs
Почему вы хотите сделать все что? Потому что, когда вы приходите вместе с Derived
объекта ...
class Derived: public Base
{
private:
int* m_pnArray;
...
... компилятор может создать отдельную виртуальную таблицу отправки ...
void* Derived::__virtual_dispatch_table[] = { (void*)&Derived::~Derived };
...ANDD выложу память производный объекта, как это:
Variable definition Memory layout
------------------- -------------
Derived derived; int n_;
void** __p_vdt = Derived::__virtual_dispatch_table;
int* m_pnArray;
Обратите внимание, что __p_vdt
находится в том же относительном положении в пределах расположения объекта, но теперь указывает на виртуальную таблицу диспетчеризации в Derived
класса?
Теперь, если вы создаете Base*
к derived
, точно такой же код, необходимый для вызова деструктора для Base
объекта, который - в случае, если вы потеряли след - был ...
void (Base::*p_destructor) = p->__p_vdt[0]
*p_destructor(p); // "p" will provide the "this" value while the destructor runs
. .. может быть запущен, но в итоге будет использоваться значение объекта __p_vdt
значение Derived::__virtual_dispatch_table
, а также поиск деструктора класса Derived
.
Предпочитаете ли вы, чтобы этого не было? – chris
Я не отвечаю на вопрос. Вы спрашиваете, почему удаление объекта 'Derived' должно вызывать деструктор' Derived'? Потому что это значит, что объект Derived должен быть уничтожен. Или вы спрашиваете об этом механизме, чтобы он корректно работал с указателем «Base»? Это точно так же, как и любой другой вызов виртуальной функции. –
Я просто хочу знать механизм, почему вызывается деструктор drived? – Sajid