виртуальный — C ++ многоуровневое наследование корректировка указателя объекта thunk

Рассмотрим следующий код с 3-уровневой иерархией множественного наследования.

auto addr = [](auto v) -> uint64_t { return *reinterpret_cast<uint64_t*>(v); };

struct BaseA
{
void virtual a() {}
};

struct BaseB
{
void virtual b() {}
};

struct BaseC : BaseA, BaseB
{
void virtual a() override {}
void virtual b() override {}
};

struct BaseD
{
void virtual d() {}
};

struct BaseE : BaseD, BaseC
{
void virtual d() override {}
void virtual a() override {}
void virtual b() override { auto a = this; std::cout << "called here: " << addr(&a) << "\n"; }
};

int main()
{

BaseE obj;

BaseE* ePtr = &obj;
BaseD* dPtr = &obj;
BaseC* cPtr = &obj;
BaseB* bPtr = &obj;
BaseA* aPtr = &obj;

ePtr->b();
cPtr->b();
bPtr->b();

std::cout << "e is at: " << addr(&ePtr) << "\n"<< "d is at: " << addr(&dPtr) << "\n"<< "a is at: " << addr(&aPtr) << "\n"<< "c is at: " << addr(&cPtr) << "\n"<< "b is at: " << addr(&bPtr) << "\n"<< "total size is " << sizeof(BaseE) << "\n"<< "vptr D and E " << vpt1 << "\n"<< "vptr A and C " << vpt2 << "\n"<< "vptr B " << vpt3 << "\n";
return 0;
}

Вывод этого прогона кода следующий:

called here: 140736308965696
called here: 140736308965696
called here: 140736308965696
e is at: 140736308965696
d is at: 140736308965696
a is at: 140736308965704
c is at: 140736308965704
b is at: 140736308965712
total size is 24
vptr D and E 4390608
vptr A and C 4390648
vptr B 4390680

Это предполагает следующую схему памяти для BaseE obj (с размером указателя 8 байт).


8 байтов, подобъект BaseD, только таблица vptr в D

8 байтов, подобъект BaseA, только vptr в таблицу A

8 байтов, подобъект BaseB, только таблица vptr to B.

Вот ePtr а также dPtr оба указывают на BaseD подобъект, оба aPtr а также cPtr указать на BaseA подобъект и bPtr в BaseB субобъект.

Мой вопрос сейчас заключается в том, какой код thunk будет генерировать компилятор для настройки this указатель в двух вызовах выше b() через указатели cPtr а также bPtr Чтобы убедиться this правильно указывает на ePtr когда BaseE реализация b() называется? поскольку cPtr а также bPtr иметь другой адрес, нужно ли знать thunk, чтобы по-разному регулировать в зависимости от того, какой тип указателя на базовый класс ему передан?

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]