在使用dynamic_cast时,查看的反汇编,假设C是派生类,A是基类
A* pa = new C;
C * c = dynamic_cast<C *>(pa);
其中调用了___RTDynamicCast,
在http://en.verysource.com/winceos-99192.html 中有
其中便有其实现,为了不和编译器中的 ___RTDynamicCast冲突,新建两个文件:rtti.h和rtti.cpp,将___RTDynamicCast修改为___RTDynamicCastMY,并注释掉一些抛异常。内容如下:
rtti.h
#pragma once
extern "C" {
#include <windows.h>
};
typedef const type_info TypeDescriptor;
struct PMD
{
ptrdiff_t mdisp; //vftable offset
ptrdiff_t pdisp; //vftable offset
ptrdiff_t vdisp; //vftable offset(for virtual base class)
};
typedef const struct _s_RTTIBaseClassDescriptor
{
TypeDescriptor *pTypeDescriptor;
DWORD numContainedBases;
PMD where;
DWORD attributes;
} _RTTIBaseClassDescriptor;
typedef const struct _s_RTTIBaseClassArray
{
_RTTIBaseClassDescriptor* arrayOfBaseClassDescriptors[3];
}_RTTIBaseClassArray;
typedef const struct _s_RTTIClassHierarchyDescriptor
{
DWORD signature;
DWORD attributes;
DWORD numBaseClasses;
_RTTIBaseClassArray *pBaseClassArray;
}_RTTIClassHierarchyDescriptor;
typedef const struct _s_RTTICompleteObjectLocator
{
DWORD signature;
DWORD offset; //vftbl相对this的偏移
DWORD cdOffset; //constructor displacement
TypeDescriptor *pTypeDescriptor;
_RTTIClassHierarchyDescriptor *pClassDescriptor;
}_RTTICompleteObjectLocator;
#define BCD_NOTVISIBLE 0x00000001
#define BCD_AMBIGUOUS 0x00000002
#define BCD_PRIVORPROTINCOMPOBJ 0x00000004
#define BCD_PRIVORPROTBASE 0x00000008
#define BCD_VBOFCONTOBJ 0x00000010
#define BCD_NONPOLYMORPHIC 0x00000020
#define BCD_PTD(bcd) ((bcd).pTypeDescriptor)
#define BCD_NUMCONTBASES(bcd) ((bcd).numContainedBases)
#define BCD_WHERE(bcd) ((bcd).where)
#define BCD_ATTRIBUTES(bcd) ((bcd).attributes)
#define CHD_MULTINH 0x00000001 //多重继承
#define CHD_VIRTINH 0x00000002 //虚拟继承
#define CHD_AMBIGUOUS 0x00000004 //有重复基类的多重继承
#define CHD_SIGNATURE(chd) ((chd).signature)
#define CHD_ATTRIBUTES(chd) ((chd).attributes)
#define CHD_NUMBASES(chd) ((chd).numBaseClasses)
#define CHD_PBCA(chd) ((chd).pBaseClassArray)
#define COL_SIGNATURE(col) ((col).signature)
#define COL_OFFSET(col) ((col).offset)
#define COL_CDOFFSET(col) ((col).cdOffset)
#define COL_PTD(col) ((col).pTypeDescriptor)
#define COL_PCHD(col) ((col).pClassDescriptor)
extern "C" PVOID __cdecl __RTDynamicCastMY(PVOID, LONG, PVOID, PVOID, BOOL);
extern "C" PVOID __cdecl __RTtypeidMY(PVOID); // ptr to vfptr
#define TYPEIDS_EQ(pID1, pID2) ((pID1 == pID2) || !strcmp(pID1->name(), pID2->name()))
rtti.cpp
#include <stdio.h>
#include <typeinfo>
#include "rtti.h"
#pragma warning(disable:4297)
static PVOID __cdecl FindCompleteObject(PVOID *);
static _RTTIBaseClassDescriptor * __cdecl FindSITargetTypeInstance(PVOID,_RTTICompleteObjectLocator *,TypeDescriptor *,int,TypeDescriptor *);
static _RTTIBaseClassDescriptor * __cdecl FindMITargetTypeInstance(PVOID,_RTTICompleteObjectLocator *,TypeDescriptor *,int,TypeDescriptor *);
static _RTTIBaseClassDescriptor * __cdecl FindVITargetTypeInstance(PVOID,_RTTICompleteObjectLocator *,TypeDescriptor *,int,TypeDescriptor *);
static ptrdiff_t __cdecl PMDtoOffset(PVOID pThis, const PMD& pmd);
extern "C" PVOID __cdecl __RTtypeidMY (PVOID inptr)
{
if (!inptr) {
//throw std::bad_typeid ("Attempted a typeid of NULL pointer!");
return NULL;
}
__try {
// Ptr to CompleteObjectLocator should be stored at vfptr[-1]
_RTTICompleteObjectLocator *pCompleteLocator = (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
return (PVOID) pCompleteLocator->pTypeDescriptor;
}
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH)
{
//throw std::__non_rtti_object ("Access violation - no RTTI data!");
}
}
extern "C" PVOID __cdecl __RTDynamicCastMY (
PVOID inptr, // Pointer to polymorphic object
LONG VfDelta, // Offset of vfptr in object
PVOID SrcType, // Static type of object pointed to by inptr
PVOID TargetType, // Desired result of cast
BOOL isReference) // TRUE if input is reference, FALSE if input is ptr
{
PVOID pResult;
_RTTIBaseClassDescriptor *pBaseClass;
if (inptr == NULL)
return NULL;
__try {
PVOID pCompleteObject = FindCompleteObject((PVOID *)inptr);
_RTTICompleteObjectLocator *pCompleteLocator = (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
// Adjust by vfptr displacement, if any
inptr = (PVOID *) ((char *)inptr - VfDelta);
// Calculate offset of source object in complete object
int inptr_delta = (char *)inptr - (char *)pCompleteObject;
if (!(CHD_ATTRIBUTES(*COL_PCHD(*pCompleteLocator)) & CHD_MULTINH)) { // if not multiple inheritance
pBaseClass = FindSITargetTypeInstance(pCompleteObject,
pCompleteLocator,
(TypeDescriptor *) SrcType,
inptr_delta,
(TypeDescriptor *) TargetType);
} else if (!(CHD_ATTRIBUTES(*COL_PCHD(*pCompleteLocator)) & CHD_VIRTINH)) { // if multiple, but not virtual, inheritance
pBaseClass = FindMITargetTypeInstance(pCompleteObject,
pCompleteLocator,
(TypeDescriptor *) SrcType,
inptr_delta,
(TypeDescriptor *) TargetType);
} else { // if virtual inheritance
pBaseClass = FindVITargetTypeInstance(pCompleteObject,
pCompleteLocator,
(TypeDescriptor *) SrcType,
inptr_delta,
(TypeDescriptor *) TargetType);
}
if (pBaseClass != NULL) {
// Calculate ptr to result base class from pBaseClass->where
pResult = ((char *) pCompleteObject) + PMDtoOffset(pCompleteObject, pBaseClass->where);
}else {
pResult = NULL;
if (isReference) {
// throw std::bad_cast("Bad dynamic_cast!");
}
}
}
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH) {
pResult = NULL;
// throw std::__non_rtti_object ("Access violation - no RTTI data!");
}
return pResult;
}
//
// FindCompleteObject - Calculate member offset from PMD & this
//
// Output: pointer to the complete object containing class *inptr
//
// Side-effects: NONE.
//
static PVOID __cdecl FindCompleteObject (PVOID *inptr) // Pointer to polymorphic object
{
// Ptr to CompleteObjectLocator should be stored at vfptr[-1]
_RTTICompleteObjectLocator *pCompleteLocator = (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
char *pCompleteObject = (char *)inptr - pCompleteLocator->offset;
// Adjust by construction displacement, if any
if (pCompleteLocator->cdOffset)
pCompleteObject += *(ptrdiff_t *)((char *)inptr - pCompleteLocator->cdOffset);
return (PVOID) pCompleteObject;
}
static _RTTIBaseClassDescriptor * __cdecl FindSITargetTypeInstance (
PVOID pCompleteObject, // pointer to complete object
_RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
TypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
int SrcOffset, // offset of source object in complete object
TypeDescriptor *pTargetTypeID) // pointer to TypeDescriptor of result of cast
{
_RTTIBaseClassDescriptor *pBase;
_RTTIBaseClassDescriptor * const *pBasePtr;
DWORD i;
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
// Test type of selected base class
pBase = *pBasePtr;
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE)) {
return pBase;
}
}
return NULL;
}
static _RTTIBaseClassDescriptor * __cdecl FindMITargetTypeInstance (
PVOID pCompleteObject, // pointer to complete object
_RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
TypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
int SrcOffset, // offset of source object in complete object
TypeDescriptor *pTargetTypeID) // pointer to TypeDescriptor of result of cast
{
_RTTIBaseClassDescriptor *pBase, *pSubBase;
_RTTIBaseClassDescriptor * const *pBasePtr, * const *pSubBasePtr;
DWORD i, j;
// First, try down-casts
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Test type of selected base class
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID)) {
// If base class is proper type, see if it contains our instance of source class
for (j = 0, pSubBasePtr = pBasePtr+1;
j < pBase->numContainedBases;
j++, pSubBasePtr++) {
pSubBase = *pSubBasePtr;
if (TYPEIDS_EQ(pSubBase->pTypeDescriptor, pSrcTypeID) &&
(PMDtoOffset(pCompleteObject, pSubBase->where) == SrcOffset)) {
// Yes, this is the proper instance of source class
return pBase;
}
}
}
}
// Down-cast failed, try cross-cast
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Check if base class has proper type, is accessible & is unambiguous
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_AMBIGUOUS)) {
return pBase;
}
}
return NULL;
}
static _RTTIBaseClassDescriptor * __cdecl FindVITargetTypeInstance (
PVOID pCompleteObject, // pointer to complete object
_RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
TypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
int SrcOffset, // offset of source object in complete object
TypeDescriptor *pTargetTypeID) // pointer to TypeDescriptor of result of cast
{
_RTTIBaseClassDescriptor *pBase, *pSubBase;
_RTTIBaseClassDescriptor * const *pBasePtr, * const *pSubBasePtr;
_RTTIBaseClassDescriptor *pResult = NULL;
DWORD i, j;
// First, try down-casts
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Test type of selected base class
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID)) {
// If base class is proper type, see if it contains our instance of source class
for (j = 0, pSubBasePtr = pBasePtr+1;
j < pBase->numContainedBases;
j++, pSubBasePtr++) {
pSubBase = *pSubBasePtr;
if (TYPEIDS_EQ(pSubBase->pTypeDescriptor, pSrcTypeID) &&
(PMDtoOffset(pCompleteObject, pSubBase->where) == SrcOffset)) {
// Yes, this is the proper instance of source class - make sure it is unambiguous
// Ambiguity now determined by inequality of offsets of source class within complete object, not pointer inequality
if ((pResult != NULL) && (PMDtoOffset(pCompleteObject, pResult->where) != PMDtoOffset(pCompleteObject, pBase->where))) {
// We already found an earlier instance, hence ambiguity
return NULL;
}
else {
// Unambiguous
pResult = pBase;
}
}
}
}
}
if (pResult != NULL)
return pResult;
// Down-cast failed, try cross-cast
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Check if base class has proper type, is accessible & is unambiguous
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_AMBIGUOUS)) {
return pBase;
}
}
return NULL;
}
static ptrdiff_t __cdecl PMDtoOffset(
PVOID pThis, // ptr to complete object
const PMD& pmd) // pointer-to-member-data structure
{
ptrdiff_t RetOff = 0;
if (pmd.pdisp >= 0) { // if base is in the virtual part of class
RetOff = pmd.pdisp;
RetOff += *(ptrdiff_t*)((char*)*(ptrdiff_t*)((char*)pThis + RetOff) + pmd.vdisp);
}
RetOff += pmd.mdisp;
return RetOff;
}
1 单继承
// WinDemo.cpp : 定义控制台应用程序的入口点。
//
#include <iostream>
#include "rtti.h"
using namespace std;
class A
{
public:
virtual void func()
{
cout << "A::func()" << endl;
}
};
class B
{
public:
virtual void func()
{
cout << "B::func()" << endl;
}
};
class C : public A
{
public:
virtual void func()
{
cout << "C::func()" << endl;
}
private:
int _val;
};
int main(int argc, char* argv[])
{
A* pa = new C;
TypeDescriptor* ptypeA = &typeid(A);
TypeDescriptor* ptypeC = &typeid(C);
C* pc = (C*)__RTDynamicCastMY(pa, 0, (LPVOID)ptypeA, (LPVOID)ptypeC, FALSE);
cout << pc << endl;
return 0;
}
类C继承类A,内存布局:
下断点:
extern "C" PVOID __cdecl __RTDynamicCastMY (
PVOID inptr, // Pointer to polymorphic object
LONG VfDelta, // Offset of vfptr in object
PVOID SrcType, // Static type of object pointed to by inptr
PVOID TargetType, // Desired result of cast
BOOL isReference) // TRUE if input is reference, FALSE if input is ptr
{
PVOID pResult;
_RTTIBaseClassDescriptor *pBaseClass;
if (inptr == NULL)
return NULL;
__try {
PVOID pCompleteObject = FindCompleteObject((PVOID *)inptr);//从基类指针的内存地址根据offset找到类的起始位置;
_RTTICompleteObjectLocator *pCompleteLocator = (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);//找到类C的虚函数表中rtti信息,存储在[-1]中
// Adjust by vfptr displacement, if any
inptr = (PVOID *) ((char *)inptr - VfDelta);
// Calculate offset of source object in complete object
int inptr_delta = (char *)inptr - (char *)pCompleteObject;//计算基类和类C的地址偏移
if (!(CHD_ATTRIBUTES(*COL_PCHD(*pCompleteLocator)) & CHD_MULTINH)) { // if not multiple inheritance 单继承情况
pBaseClass = FindSITargetTypeInstance(pCompleteObject,
pCompleteLocator,
(TypeDescriptor *) SrcType,
inptr_delta,
(TypeDescriptor *) TargetType);
}
......
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH) {
pResult = NULL;
// throw std::__non_rtti_object ("Access violation - no RTTI data!");
}
return pResult;
}
其中:
(_RTTICompleteObjectLocator *)((*((void***)inptr))[-1])
是取出虚表中的前一项,,虚表的前一项是RTTI的信息,这个结构的具体信息:
_RTTICompleteObjectLocator
这个是整个RTTI的结构定义,具体结构如下:
typedef const struct _s_RTTICompleteObjectLocator {
DWORD signature;
DWORD offset;
DWORD cdOffset;
TypeDescriptor *pTypeDescriptor;
_RTTIClassHierarchyDescriptor *pClassDescriptor;
} _RTTICompleteObjectLocator;
其中:
signature
: RTTI的签名。offset
: 相对于对象开始的偏移量.cdOffset
: 暂时不知道什么意思。pTypeDescriptor
: 类的type_info
结构。pClassDescriptor
: 基类的描述信息。
TypeDescriptor
TypeDescriptor 即 type_info ,type_info 中有一个成员变量:
mutable __std_type_info_data _Data;
其中_DecoratedName记录了当前类的名称
typedef const type_info TypeDescriptor;
class type_info
{
public:
type_info(const type_info&) = delete;
type_info& operator=(const type_info&) = delete;
size_t hash_code() const noexcept
{
return __std_type_info_hash(&_Data);
}
bool operator==(const type_info& _Other) const noexcept
{
return __std_type_info_compare(&_Data, &_Other._Data) == 0;
}
bool operator!=(const type_info& _Other) const noexcept
{
return __std_type_info_compare(&_Data, &_Other._Data) != 0;
}
bool before(const type_info& _Other) const noexcept
{
return __std_type_info_compare(&_Data, &_Other._Data) < 0;
}
const char* name() const noexcept
{
#ifdef _M_CEE_PURE
return __std_type_info_name(&_Data, static_cast<__type_info_node*>(__type_info_root_node.ToPointer()));
#else
return __std_type_info_name(&_Data, &__type_info_root_node);
#endif
}
const char* raw_name() const noexcept
{
return _Data._DecoratedName;
}
virtual ~type_info() noexcept;
private:
mutable __std_type_info_data _Data;
};
struct __std_type_info_data
{
const char * _UndecoratedName;
const char _DecoratedName[1];
__std_type_info_data() = delete;
__std_type_info_data(const __std_type_info_data&) = delete;
__std_type_info_data(__std_type_info_data&&) = delete;
__std_type_info_data& operator=(const __std_type_info_data&) = delete;
__std_type_info_data& operator=(__std_type_info_data&&) = delete;
};
_RTTIClassHierarchyDescriptor
typedef const struct _s_RTTIClassHierarchyDescriptor {
DWORD signature;
DWORD attributes;
DWORD numBaseClasses;
_RTTIBaseClassArray *pBaseClassArray;
} _RTTIClassHierarchyDescriptor;
#define CHD_MULTINH 0x00000001
#define CHD_VIRTINH 0x00000002
#define CHD_AMBIGUOUS 0x00000004
其中 attributes的定义为CHD_xxxx分别如下:
CHD_MULTINH=0x00000001 : 表示多继承。
CHD_VIRTINH=0x00000002 : 存在虚拟继承。
CHD_AMBIGUOUS=0x00000004 : 继承情况模糊不清。
numBaseClasses : 表示基类的个数。
pBaseClassArray : 基类的描述数组。
_RTTIBaseClassArray
这个结构是基类数组描述,结构定义如下:其中存储了一个的基类,其中包括自己
typedef const struct _s_RTTIBaseClassArray {
_RTTIBaseClassDescriptor *arrayOfBaseClassDescriptors[];
} _RTTIBaseClassArray;
typedef const struct _s_RTTIBaseClassDescriptor {
TypeDescriptor *pTypeDescriptor;
DWORD numContainedBases;
PMD where;
DWORD attributes;
} _RTTIBaseClassDescriptor;
typedef struct PMD
{
ptrdiff_t mdisp; // Offset of intended data within base
ptrdiff_t pdisp; // Displacement to virtual base pointer
ptrdiff_t vdisp; // Index within vbTable to offset of base
} PMD;
#define BCD_NOTVISIBLE 0x00000001
#define BCD_AMBIGUOUS 0x00000002
#define BCD_PRIVORPROTINCOMPOBJ 0x00000004
#define BCD_PRIVORPROTBASE 0x00000008
#define BCD_VBOFCONTOBJ 0x00000010
#define BCD_NONPOLYMORPHIC 0x00000020
如:
(1) C单继承A,因此offset为0;
(2)_DecoratedName中可以看出类C存储的名称为:0x001bd154 ".?AVC@@"
(3)从pBaseClassArray中,可以看出类C有两个基类,分别是C,A 为什么要记录C呢,这个东西在dynastic_cast中有用
计算单继承中 down_cast:
static _RTTIBaseClassDescriptor * __cdecl FindSITargetTypeInstance (
PVOID pCompleteObject, // pointer to complete object
_RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
TypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
int SrcOffset, // offset of source object in complete object
TypeDescriptor *pTargetTypeID) // pointer to TypeDescriptor of result of cast
{
_RTTIBaseClassDescriptor *pBase;
_RTTIBaseClassDescriptor * const *pBasePtr;
DWORD i;
//从基类的数组中查找是否存在匹配的基类,如果存在则返回
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
// Test type of selected base class
pBase = *pBasePtr;
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE)) {
return pBase;
}
}
return NULL;
}
2 多继承
// WinDemo.cpp : 定义控制台应用程序的入口点。
//
#include <iostream>
#include "rtti.h"
using namespace std;
class A
{
public:
virtual void func()
{
cout << "A::func()" << endl;
}
};
class B
{
public:
virtual void func()
{
cout << "B::func()" << endl;
}
};
class C : public B,public A
{
public:
virtual void func()
{
cout << "C::func()" << endl;
}
private:
int _val;
};
int main(int argc, char* argv[])
{
A* pa = new C;
TypeDescriptor* ptypeA = &typeid(A);
TypeDescriptor* ptypeC = &typeid(C);
C* pc = (C*)__RTDynamicCastMY(pa, 0, (LPVOID)ptypeA, (LPVOID)ptypeC, FALSE);
cout << pc << endl;
return 0;
}
其中,特意让C先继承B,这样当 A* pa = new C; 时 A类的虚函数指针在类C中的内存中有偏移,如下:
在FindCompleteObject 中,
会根据基类A类型的指针,通过虚表中_RTTICompleteObjectLocator记录的offset找到类C的开始地址
static PVOID __cdecl FindCompleteObject (PVOID *inptr) // Pointer to polymorphic object
{
// Ptr to CompleteObjectLocator should be stored at vfptr[-1]
_RTTICompleteObjectLocator *pCompleteLocator = (_RTTICompleteObjectLocator *) ((*((void***)inptr))[-1]);
char *pCompleteObject = (char *)inptr - pCompleteLocator->offset;
// Adjust by construction displacement, if any
if (pCompleteLocator->cdOffset)
pCompleteObject += *(ptrdiff_t *)((char *)inptr - pCompleteLocator->cdOffset);
return (PVOID) pCompleteObject;
}
即 char *pCompleteObject = (char *)inptr - pCompleteLocator->offset;找到类C的内存开始地址
多继承下dynastic_cast转换:
static _RTTIBaseClassDescriptor * __cdecl FindMITargetTypeInstance (
PVOID pCompleteObject, // pointer to complete object
_RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
TypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
int SrcOffset, // offset of source object in complete object
TypeDescriptor *pTargetTypeID) // pointer to TypeDescriptor of result of cast
{
_RTTIBaseClassDescriptor *pBase, *pSubBase;
_RTTIBaseClassDescriptor * const *pBasePtr, * const *pSubBasePtr;
DWORD i, j;
// First, try down-casts 首先找到目标类C
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Test type of selected base class
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID)) {
// If base class is proper type, see if it contains our instance of source class
//如果找到目标类C,继续找看是否能找到目标类A,以证明存在合法的继承关系
for (j = 0, pSubBasePtr = pBasePtr+1;
j < pBase->numContainedBases;
j++, pSubBasePtr++) {
pSubBase = *pSubBasePtr;
if (TYPEIDS_EQ(pSubBase->pTypeDescriptor, pSrcTypeID) &&
(PMDtoOffset(pCompleteObject, pSubBase->where) == SrcOffset)) {
// Yes, this is the proper instance of source class
return pBase;//找到,返回类C的内存起始地址
}
}
}
}
// Down-cast failed, try cross-cast
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Check if base class has proper type, is accessible & is unambiguous
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_AMBIGUOUS)) {
return pBase;
}
}
return NULL;
}
用A* 指向派生类,offset为4;
_Data中 时:?AVC@@ 即类C;
attributes:1 表示多继承
pClassDescriptor:中看到有三个基类C B A 其中A的mdisp=4,即在A类虚函数指针在内存布局中的偏移
参考:
C++ dynamic_cast实现原理_passion_wu128的专栏-CSDN博客_dynamic_cast原理
C++ RTTI 实现原理详解_xdesk的专栏-CSDN博客_c++ rtti
dynamic_cast, RTTI, 整理 - Dirichlet - 博客园
工程资源:https://download.csdn.net/download/LIJIWEI0611/31230142