为什么这是相同的,即使对象指针不同的多继承? [英] Why is this the same even when object pointers differ in multiple inheritance?
问题描述
当使用多重继承时,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屋!