菱形虚继承
菱形虚继承是多继承和虚继承的复合
验证:顺序
派生类VPtr虚表;
派生类VBPtr表;
派生类成员;
公共基类VPtr;
公共基类成员;
首个基类VPtr虚表; (继承列表顺序)
首个基类VBPtr表;
首个基类成员;
第二个基类VPtr虚表;
第二个基类VBPtr虚表
第二个基类成员;
…
环境:VS2017
*.h
//基类3
class FBase3 : virtual public FBase
{
public:
char m_cBase3Memeber;
public:
//构造
FBase3() {}
//虚析构
virtual ~FBase3() {}
public:
virtual void Base3VirtualFun1() { std::cout << "FBase3::BaseVirtualFun1()\n"; }
virtual void Base3VirtualFun2() { std::cout << "FBase3::BaseVirtualFun2()\n"; }
};
//基类4
class FBase4 : virtual public FBase
{
public:
char m_cBase4Memeber;
public:
//构造
FBase4() {}
//虚析构
virtual ~FBase4() {}
public:
virtual void Base4VirtualFun1() { std::cout << "FBase4::BaseVirtualFun1()\n"; }
virtual void Base4VirtualFun2() { std::cout << "FBase4::BaseVirtualFun2()\n"; }
};
//菱形虚继承
class FDiamondInheritanceDerive : virtual public FBase4, virtual public FBase3
{
public:
//构造
FDiamondInheritanceDerive() {}
//虚析构
virtual ~FDiamondInheritanceDerive() {}
public:
//重写 基类虚函数
virtual void BaseVirtualFun1() override { std::cout << "FDiamondInheritanceDerive::BaseVirtualFun1()\n"; }
//重写 基类3虚函数
virtual void Base3VirtualFun1() override { std::cout << "FDiamondInheritanceDerive::Base3VirtualFun1()\n"; }
//新增虚函数
virtual void VirtualFun3() { std::cout << "FDiamondInheritanceDerive::VirtualFun3()\n"; }
public:
//成员
char m_cDiamondInheritanceDeriveMemeber;
};
/* 配置属性-》C++ -》命令行: /d1 reportAllClassLayout
//--------------------------------------------x86--------------------------------------------
1>class FDiamondInheritanceDerive size(40):
1> +---
1> 0 | {vfptr}
1> 4 | {vbptr}
1> 8 | m_cDiamondInheritanceDeriveMemeber
1> +---
1>FDiamondInheritanceDerive::$vftable@:
1> | &FDiamondInheritanceDerive_meta
1> | 0
1> 0 | &FDiamondInheritanceDerive::VirtualFun3
1>
1>FDiamondInheritanceDerive::$vbtable@FDiamondInheritanceDerive@:
1> 0 | -4
1> 1 | 9 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+4)FBase)
1> 2 | 14 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+4)FBase4)
1> 3 | 27 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+4)FBase3)
1>
1>FDiamondInheritanceDerive::$vftable@FBase@:
1> | -13
1> 0 | &(vtordisp) FDiamondInheritanceDerive::BaseVirtualFun1
1> 1 | &FBase::BaseVirtualFun2
1>
1>FDiamondInheritanceDerive::$vftable@FBase4@:
1> | -18
1> 0 | &FDiamondInheritanceDerive::{dtor}
1> 1 | &FBase4::Base4VirtualFun1
1> 2 | &FBase4::Base4VirtualFun2
1>
1>FDiamondInheritanceDerive::$vbtable@FBase4@:
1> 0 | -4
1> 1 | -9 (FDiamondInheritanceDerived(FBase4+4)FBase)
1>
1>FDiamondInheritanceDerive::$vftable@FBase3@:
1> | -31
1> 0 | &(vtordisp) thunk: this-=13; goto FDiamondInheritanceDerive::{dtor}
1> 1 | &(vtordisp) FDiamondInheritanceDerive::Base3VirtualFun1
1> 2 | &FBase3::Base3VirtualFun2
1>
1>FDiamondInheritanceDerive::$vbtable@FBase3@:
1> 0 | -4
1> 1 | -22 (FDiamondInheritanceDerived(FBase3+4)FBase)
1>
//--------------------------------------------x64--------------------------------------------
1>class FDiamondInheritanceDerive size(68):
1> +---
1> 0 | {vfptr}
1> 8 | {vbptr}
1>16 | m_cDiamondInheritanceDeriveMemeber
1> +---
1>17 | (vtordisp for vbase FBase)
1> +--- (virtual base FBase)
1>21 | {vfptr}
1>29 | m_cBaseMemeber
1> +---
1> +--- (virtual base FBase4)
1>30 | {vfptr}
1>38 | {vbptr}
1>46 | m_cBase4Memeber
1> +---
1>47 | (vtordisp for vbase FBase3)
1> +--- (virtual base FBase3)
1>51 | {vfptr}
1>59 | {vbptr}
1>67 | m_cBase3Memeber
1> +---
1>
1>FDiamondInheritanceDerive::$vftable@:
1> | &FDiamondInheritanceDerive_meta
1> | 0
1> 0 | &FDiamondInheritanceDerive::VirtualFun3
1>
1>FDiamondInheritanceDerive::$vbtable@FDiamondInheritanceDerive@:
1> 0 | -8
1> 1 | 13 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+8)FBase)
1> 2 | 22 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+8)FBase4)
1> 3 | 43 (FDiamondInheritanceDerived(FDiamondInheritanceDerive+8)FBase3)
1>
1>FDiamondInheritanceDerive::$vftable@FBase@:
1> | -21
1> 0 | &(vtordisp) FDiamondInheritanceDerive::BaseVirtualFun1
1> 1 | &FBase::BaseVirtualFun2
1>
1>FDiamondInheritanceDerive::$vftable@FBase4@:
1> | -30
1> 0 | &FDiamondInheritanceDerive::{dtor}
1> 1 | &FBase4::Base4VirtualFun1
1> 2 | &FBase4::Base4VirtualFun2
1>
1>FDiamondInheritanceDerive::$vbtable@FBase4@:
1> 0 | -8
1> 1 | -17 (FDiamondInheritanceDerived(FBase4+8)FBase)
1>
1>FDiamondInheritanceDerive::$vftable@FBase3@:
1> | -51
1> 0 | &(vtordisp) thunk: this-=21; goto FDiamondInheritanceDerive::{dtor}
1> 1 | &(vtordisp) FDiamondInheritanceDerive::Base3VirtualFun1
1> 2 | &FBase3::Base3VirtualFun2
1>
1>FDiamondInheritanceDerive::$vbtable@FBase3@:
1> 0 | -8
1> 1 | -38 (FDiamondInheritanceDerived(FBase3+8)FBase)
1>
vtordisp
vtordisp是一个C++编译器的实现细节,主要用于解决类的多继承中虚函数表指针的偏移问题。在C++多继承中,每个基类都有自己的虚函数表指针,但是在派生类中只能有一个虚函数表指针,所以需要通过vtordisp来计算每个基类的虚函数表指针在派生类中的偏移量,从而实现正确的调用。
vtordisp的具体实现方式因编译器而异,例如在Visual C++中使用了虚基类表和偏移量表来计算偏移量。虚基类表是一个全局表,用于存储虚基类的偏移量和虚函数表指针。偏移量表则是每个类的成员变量之前添加的一段空间,在其中存储了各个基类在当前类中的偏移量,包括虚基类和非虚基类。通过这些表的信息,编译器可以在派生类中正确地计算出每个基类的虚函数表指针在派生类中的偏移量。
需要注意的是,vtordisp只在多继承的情况下才会使用,对于单继承的类,虚函数表指针不需要进行偏移。同时,由于vtordisp是编译器的实现细节,因此不建议在代码中直接使用vtordisp。
*/
*.cpp
/*
菱形虚继承
菱形虚继承是多继承和虚继承的复合
验证:顺序
*/
void DiamondInheritanceDerive_Test()
{
std::cout << std::endl << std::endl << "------------------------------------DiamondInheritanceDerive_Test-------------------------Start" << std::endl;
FDiamondInheritanceDerive DiamondInheritanceDerive;
DiamondInheritanceDerive.m_cBaseMemeber = 10;
DiamondInheritanceDerive.m_cBase3Memeber = 23;
DiamondInheritanceDerive.m_cBase4Memeber = 24;
DiamondInheritanceDerive.m_cDiamondInheritanceDeriveMemeber = 30;
//结构大小
STREXE_D(sizeof(DiamondInheritanceDerive));//x64-68; x86-40;
//DiamondInheritanceDerive Function
pFun* DiamondInheritanceDeriveVptr = nullptr;
//Base Function
pFun* BaseF1 = nullptr;
int nPointerSize = 0;
#ifdef _WIN64
long long *llV_ptr = (long long*)&DiamondInheritanceDerive;
//首地址
std::cout << "VPtr地址ll:" << std::hex << *llV_ptr << std::endl;
std::cout << "&DiamondInheritanceDerive:" << std::hex << &DiamondInheritanceDerive << std::endl;
STREXE_HEX((long long*)&(DiamondInheritanceDerive.m_cDiamondInheritanceDeriveMemeber));
STREXE_HEX((long long*)&(DiamondInheritanceDerive.m_cBaseMemeber));
STREXE_HEX((long long*)&(DiamondInheritanceDerive.m_cBase4Memeber));
STREXE_HEX((long long*)&(DiamondInheritanceDerive.m_cBase3Memeber));
//DiamondInheritanceDerive Function
//pFun* DiamondInheritanceDeriveVptr = nullptr;
BaseVirtualFun_Test* pBaseVPtr = nullptr;
BaseVirtualFun_Test* pBase4VPtr = nullptr;
BaseVirtualFun_Test* pBase3VPtr = nullptr;
//默认构造内的一个指针,占4个字节
nPointerSize = sizeof(long long);
DiamondInheritanceDeriveVptr = (pFun*)((char*)(*llV_ptr));
//虚基类表指针
long long * pDiamondInheritanceDeriveMem = (long long *)((char*)(&DiamondInheritanceDerive) + nPointerSize);
long long * pVbptr = (long long *)((char*)(pDiamondInheritanceDeriveMem)+sizeof(char));
//long long* lBaseV_ptr = (long long*)((char*)(pVbptr) + nPointerSize);// (long long*)((((char*)pDiamondInheritanceDeriveMem) + nPointerSize));
//BaseF1 = (pFun*)(*lBaseV_ptr);
long long* BaseMemeber = (long long*)((char*)(&DiamondInheritanceDerive) + sizeof(DiamondInheritanceDerive) - sizeof(char));
long long* lBaseV_ptr = (long long*)((char*)(&DiamondInheritanceDerive) + sizeof(DiamondInheritanceDerive) - sizeof(char) - nPointerSize);
//long long * pVbptr = (long long*)((char*)(&DiamondInheritanceDerive) + sizeof(DiamondInheritanceDerive) - sizeof(char) - nPointerSize - nPointerSize);
BaseF1 = (pFun*)(*lBaseV_ptr);//140699019104880 0x7FF7 0B0D D270
pBaseVPtr = (BaseVirtualFun_Test*)(long long*)(*(long long*)((char*)&DiamondInheritanceDeriveVptr) + 24);
pBase4VPtr = (BaseVirtualFun_Test*)(long long*)((long long*)((char*)pBaseVPtr+ 32) );
pBase3VPtr = (BaseVirtualFun_Test*)(long long*)((long long*)((char*)pBase4VPtr+ 40) );
//DiamondInheritanceDerive函数调用
std::cout << "DiamondInheritanceDerive函数调用:--------------------------------" << std::endl;
STREXE_HEX(DiamondInheritanceDeriveVptr);
(*DiamondInheritanceDeriveVptr)();
STREXE_HEX(pBaseVPtr);
BaseVirtualFun_Test BaseF = *(BaseVirtualFun_Test *)(pBaseVPtr);
(DiamondInheritanceDerive.*BaseF)();
STREXE_HEX(pBase4VPtr);
BaseVirtualFun_Test BaseF4_1 = *(BaseVirtualFun_Test *)(pBase4VPtr + 1);//跳过虚析构函数
(DiamondInheritanceDerive.*BaseF4_1)();
BaseVirtualFun_Test BaseF4_2 = *(BaseVirtualFun_Test *)(pBase4VPtr + 2);
(DiamondInheritanceDerive.*BaseF4_2)();
//STREXE_HEX(pBase3VPtr);
BaseVirtualFun_Test BaseF3_1 = *(BaseVirtualFun_Test *)(pBase3VPtr + 1);//跳过虚析构函数
BaseVirtualFun_Test BaseF3_2 = *(BaseVirtualFun_Test *)(pBase3VPtr + 2);
(DiamondInheritanceDerive.*BaseF3_1)();
(DiamondInheritanceDerive.*BaseF3_2)();
#else
#ifdef _WIN32
//首地址
long *lV_ptr = (long *)&DiamondInheritanceDerive;
std::cout << "VPtr地址l:" << std::hex << *lV_ptr << std::endl;
std::cout << "&DiamondInheritanceDerive:" << std::hex << &DiamondInheritanceDerive << std::endl;
STREXE_HEX((long*)&(DiamondInheritanceDerive.m_cDiamondInheritanceDeriveMemeber));
STREXE_HEX((long*)&(DiamondInheritanceDerive.m_cBaseMemeber));
STREXE_HEX((long*)&(DiamondInheritanceDerive.m_cBase4Memeber));
STREXE_HEX((long*)&(DiamondInheritanceDerive.m_cBase3Memeber));
//默认构造内的一个指针
nPointerSize = sizeof(long);
DiamondInheritanceDeriveVptr = (pFun*)(*lV_ptr);
//虚基类表指针
long * pDiamondInheritanceDeriveMem = (long *)((char*)(&DiamondInheritanceDerive) + nPointerSize);
long * pVbptr = (long *)(((char*)pDiamondInheritanceDeriveMem) + sizeof(char));
long* lBaseV_ptr = (long*)((((char*)pVbptr) + nPointerSize));
BaseF1 = (pFun*)(*lBaseV_ptr);
long* BaseMemeber = (long*)((char*)lBaseV_ptr + nPointerSize);
pFun* pBaseVPtr = nullptr;
pFun* pBase4VPtr = nullptr;
pFun* pBase4VBPtr = nullptr;
pFun* pBase3VPtr = nullptr;
pBaseVPtr = (pFun*)(((char*)DiamondInheritanceDeriveVptr) + 12);
pBase4VPtr = (pFun*)(((char*)pBaseVPtr) + 16);
pBase3VPtr = (pFun*)(((char*)pBase4VPtr) + 20);
//DiamondInheritanceDerive函数调用
std::cout << "DiamondInheritanceDerive函数调用:--------------------------------" << std::endl;
STREXE_HEX(DiamondInheritanceDeriveVptr);
(*DiamondInheritanceDeriveVptr)();
STREXE_HEX(pBaseVPtr);
(*pBaseVPtr)();
STREXE_HEX(pBase4VPtr);
(*(pBase4VPtr + 1))();//跳过虚析构函数
(*(pBase4VPtr + 2))();
STREXE_HEX(pBase3VPtr);
(*(pBase3VPtr + 1))();//跳过虚析构函数
(*(pBase3VPtr + 2))();
STREXE_HEX((long *)(((char*)lV_ptr) + 8));
STREXE_D((char)(*(((char*)lV_ptr) + 8)));
STREXE_HEX((long *)(((char*)lV_ptr) + 8 + 9));
STREXE_D((char)(*(((char*)lV_ptr) + 8 + 9)));
STREXE_HEX((long *)(((char*)lV_ptr) + 8 + 9 + 9));
STREXE_D((char)(*(((char*)lV_ptr) + 8 + 9 + 9)));
STREXE_HEX((long *)(((char*)lV_ptr) + 8 + 9 + 9 + 13));
STREXE_D((char)(*(((char*)lV_ptr) + 8 + 9 + 9 + 13)));
STREXE_HEX(lV_ptr);
STREXE_HEX(*lV_ptr);
pFun *pVirtualFun3 = (pFun*)(*(long *)(((char*)lV_ptr) /*+ nPointerSize*/));
STREXE_HEX(pVirtualFun3);
//派生类新增虚函数
(*(pVirtualFun3))(); //FDiamondInheritanceDerive::VirtualFun3()
//m_cDiamondInheritanceDeriveMemeber
STREXE_HEX((long *)(((char*)lV_ptr) + 2 * nPointerSize));
STREXE_D((char)(*(((char*)lV_ptr) + 2 * nPointerSize)));
//4个未知空间????vtordisp
//vbptr
long* vbptr = (long *)((lV_ptr + 1));
int nDerive2VBPtr = (int)(*(((long*)(*vbptr))));
STREXE_D(nDerive2VBPtr);//nDerive2VBPtr: -4
//Base
int nBase2VBPtr = (int)(*(((long*)(*vbptr)) + 1));
STREXE_D(nBase2VBPtr);//nBase2VBPtr: 9
long* pBaseBPtr = (long*)(((char*)vbptr) + nBase2VBPtr);
pFun * pBaseVirtualFun1 = (pFun *)(*pBaseBPtr);
(*pBaseVirtualFun1)();//FDiamondInheritanceDerive::BaseVirtualFun1()
pFun * pBaseVirtualFun2 = (pFun *)(*pBaseBPtr) + 1;
(*pBaseVirtualFun2)(); //FBase::BaseVirtualFun2()
//m_cBaseMemeber
long* pm_cBaseMemeber = pBaseBPtr + 1;
STREXE_HEX(pm_cBaseMemeber);
STREXE_D((char)(*pm_cBaseMemeber));
//Base4
int nBase42VBPtr = (int)(*(((long*)(*vbptr)) + 2));
STREXE_D(nBase42VBPtr);//nBase42VBPtr: 14
long* pBase4BPtr = (long*)(((char*)vbptr) + nBase42VBPtr);
pFun * pBase4VirtualFun1 = (pFun *)(*pBase4BPtr) + 1;//跳过虚析构
(*pBase4VirtualFun1)(); //FBase4::BaseVirtualFun1()
pFun * pBase4VirtualFun2 = (pFun *)(*pBase4BPtr) + 2;
(*pBase4VirtualFun2)(); //FBase4::BaseVirtualFun2()
//Base4::vbptr
long* pBase4_vbptr = pBase4BPtr + 1;
int nVBPtr42VPtr = (int)(*(((long*)(*pBase4_vbptr))));
STREXE_D(nVBPtr42VPtr);//nVBPtr42VPtr: -4
int nVBPtr42BaseVPtr = (int)(*(((long*)(*pBase4_vbptr)) + 1));
STREXE_D(nVBPtr42BaseVPtr);//nVBPtr42BaseVPtr: -9
//m_cBase4Memeber
long* pm_cBase4Memeber = pBase4BPtr + 1 + 1;
STREXE_HEX(pm_cBase4Memeber);
STREXE_D((char)(*pm_cBase4Memeber));
//4个未知空间????vtordisp
//Base3
int nVBPtr2Base3VPtr = (int)(*(((long*)(*vbptr)) + 3));
STREXE_D(nVBPtr2Base3VPtr);//nVBPtr2Base3VPtr: 27
long* pBase3BPtr = (long*)(((char*)vbptr) + nVBPtr2Base3VPtr);
pFun * pBase3VirtualFun1 = (pFun *)(*pBase3BPtr) + 1;//跳过虚析构
(*pBase3VirtualFun1)(); //FDiamondInheritanceDerive::Base3VirtualFun1()
pFun * pBase3VirtualFun2 = (pFun *)(*pBase3BPtr) + 2;
(*pBase3VirtualFun2)(); //FBase3::BaseVirtualFun2()
//Base3::vbptr
long* pBase3_vbptr = pBase3BPtr + 1;
int nVBPtr32VPtr = (int)(*(((long*)(*pBase3_vbptr))));
STREXE_D(nVBPtr32VPtr);//nVBPtr32VPtr: -4
int nVBPtr32BaseVPtr = (int)(*(((long*)(*pBase3_vbptr)) + 1));
STREXE_D(nVBPtr32BaseVPtr);//nVBPtr32BaseVPtr: -22
//m_cBase3Memeber
long* pm_cBase3Memeber = pBase3BPtr + 1 + 1;
STREXE_HEX(pm_cBase3Memeber);
STREXE_D((char)(*pm_cBase3Memeber));//(char)(*pm_cBase3Memeber): 23
//4个未知空间????vtordisp
#endif
#endif
std::cout << "------------------------------------DiamondInheritanceDerive_Test-------------------------End" << std::endl;
}