为什么这是相同的,即使对象指针不同的多继承? [英] Why is this the same even when object pointers differ in multiple inheritance?

查看:158
本文介绍了为什么这是相同的,即使对象指针不同的多继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用多重继承时,C ++必须维护几个vtables,这会导致共同基类的几个视图。

When using multiple inheritance C++ has to maintain several vtables which leads to having "several views" of common base classes.

这里是一个代码片段:

#include "stdafx.h"
#include <Windows.h>

void dumpPointer( void* pointer )
{
    __int64 thisPointer = reinterpret_cast<__int64>( pointer );
    char buffer[100];
   _i64toa( thisPointer, buffer, 10 );
    OutputDebugStringA( buffer );
    OutputDebugStringA( "\n" );
}

class ICommonBase {
public:
    virtual void Common() = 0 {}
};

class IDerived1 : public ICommonBase {
};

class IDerived2 : public ICommonBase {
};

class CClass : public IDerived1, public IDerived2 {
public:
    virtual void Common() {
        dumpPointer( this );
    }
    int stuff;
};

int _tmain(int argc, _TCHAR* argv[])
{
    CClass* object = new CClass();
    object->Common();
    ICommonBase* casted1 = static_cast<ICommonBase*>( static_cast<IDerived1*>( object ) );
    casted1->Common();
    dumpPointer( casted1 );

    ICommonBase* casted2 = static_cast<ICommonBase*>( static_cast<IDerived2*>( object ) );
    casted2->Common();
    dumpPointer( casted2 );

    return 0;
}

它会产生以下输出:

206968 //CClass::Common this
206968 //(ICommonBase)IDerived1::Common this
206968 //(ICommonBase)IDerived1* casted1
206968 //(ICommonBase)IDerived2::Common this
206972 //(ICommonBase)IDerived2* casted2

这里 casted1 casted2 有不同的值,这是合理的,因为他们指向不同的子对象。在调用虚函数的时候,对基类的转换已经完成,编译器不知道它最初是一个最派生的类。仍然每次 都是相同的。

here casted1 and casted2 have different values which is reasonable since they point to different subobjects. At the point when the virtual function is called the cast to the base class has been done and the compiler doesn't know that it was a most derived class originally. Still this is the same each time. How does it happen?

推荐答案

当在虚函数调用中使用多重继承时,对虚函数的调用通常会到调整这个指针的'thunk'。在你的例子中, casted1 指针的vtbl条目不需要thunk因为 IDerived1 code> CClass 恰好与CClass对象的开始一致(这就是为什么 casted1 指针值与 CClass object 指针)。

When multiple inheritance is used in a virtual function call, the call to the virtual function will often go to a 'thunk' that adjusts the this pointer. In your example, the casted1 pointer's vtbl entry doesn't need a thunk becuase the IDerived1 sub-object of the CClass happens to coincide with the start of the CClass object (which is why the casted1 pointer value is the same as the CClass object pointer).

指向 IDerived2 子对象的指针不符合 CClass code> object,因此vtbl函数指针实际上指向一个thunk而不是直接到 CClass :: Common()函数。 thunk调整这个指针指向实际的 CClass 对象,然后跳转到 CClass :: Common()函数。因此,它将总是获得指向 CClass 对象的开始的指针,而不管它可能从哪个类型的子对象指针调用。

However, the casted2 pointer to the IDerived2 sub-object doesn't coincide with the start of the CClass object, so the vtbl function pointer actually points to a thunk instead of directly to the CClass::Common() function. The thunk adjusts the this pointer to point to the actual CClass object then jumps to the CClass::Common() function. So it will always get a pointer to the start of the CClass object, regardless of which type of sub-object pointer it might have been called from.

在S tanley中有一个很好的解释Lippman的C ++对象模型内部一书,第4.2节虚拟成员函数/ MI下的虚拟函数。

There's a very good explanation of this in Stanley Lippman's "Inside the C++ Object Model" book, section 4.2 "Virtual Member Functions/Virtual Functions Under MI".

这篇关于为什么这是相同的,即使对象指针不同的多继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆