C ++多级继承thunk对象指针调整

时间:2018-06-02 15:09:36

标签: c++ virtual multiple-inheritance memory-layout virtual-table

考虑以下具有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到B表。

此处ePtrdPtr都指向BaseD子对象,aPtrcPtr都指向BaseA子对象和{{1} }到bPtr子对象。

我现在的问题是编译器生成什么thunk代码,通过指针BaseBthis调整b()以上两个调用中的cPtr指针,以确保调用bPtr的{​​{1}}时,this正确指向ePtr?由于BaseEb()具有不同的地址,thunk需要知道根据传递给它的Base类指针的类型进行不同的调整吗?

0 个答案:

没有答案