【RTTI】编写代码实现,获取虚函数对象的类名

导读

开发环境

版本号描述
文章日期2022-11-09
操作系统Win11-21H2内部版本号22000.588
Visual Studio 201916.11.12

编写代码实现

效果

在这里插入图片描述

代码实现

#pragma once

#include <windows.h>

struct TypeDescriptor
{
	DWORD ptrToVTable;
	DWORD spare;
	char name[1];
};
struct PMD
{
	int mdisp;  //member displacement
	int pdisp;  //vbtable displacement
	int vdisp;  //displacement inside vbtable
};
struct RTTIBaseClassDescriptor
{
	struct TypeDescriptor* pTypeDescriptor; //type descriptor of the class
	DWORD numContainedBases; //number of nested classes following in the Base Class Array
	struct PMD where;        //pointer-to-member displacement info
	DWORD attributes;        //flags, usually 0
};
struct RTTIClassHierarchyDescriptor
{
	DWORD signature;      //always zero?
	DWORD attributes;     //bit 0 set = multiple inheritance, bit 1 set = virtual inheritance
	DWORD numBaseClasses; //number of classes in pBaseClassArray
	struct RTTIBaseClassArray* pBaseClassArray;
};
typedef RTTIClassHierarchyDescriptor* PRTTIClassHierarchyDescriptor;
struct RTTICompleteObjectLocator
{
	DWORD signature; //always zero ?
	DWORD offset;    //offset of this vtable in the complete class
	DWORD cdOffset;  //constructor displacement offset
	struct TypeDescriptor* pTypeDescriptor; //TypeDescriptor of the complete class
	struct RTTIClassHierarchyDescriptor* pClassHierarchyDescriptor; //describes inheritance hierarchy
};
typedef RTTICompleteObjectLocator* PRTTICompleteObjectLocator;

namespace my
{
	DWORD ReadDword32(PVOID obj)
	{
		return *(PDWORD)obj;
	}
	DWORD ReadDword32(DWORD obj)
	{
		return *(PDWORD)obj;
	}

	// vtable 地址
	DWORD GetVTableByObj(PVOID obj)
	{
		return ReadDword32(obj);
	}

	// RTTICompleteObjectLocator
	// vtable - 4
	PRTTICompleteObjectLocator GetRttiColByObj(PVOID obj)
	{
		return (PRTTICompleteObjectLocator)ReadDword32(GetVTableByObj(obj) - 4);
	}

	// 获取虚函数对象的类名
	char* GetObjectClassName(PVOID obj)
	{
		PRTTICompleteObjectLocator pCol = GetRttiColByObj(obj);
		return pCol->pTypeDescriptor->name;
	}

}

测试代码



class CFu
{
public:
    CFu(): a(1), b(2) {}

    int a;
    int b;
};

class CZi2 : public CFu
{
public:
	CZi2() : a(3), c(4) {}
	// 类中必须包含虚函数
    virtual ~CZi2() {};

	int a;
	int c;
};

void foobar()
{
    CZi2 zi;
	char* className = my::GetObjectClassName(&zi);
	MyLogD("className = %s \n", className);
	
	// std::string不包含虚函数,下面代码会崩溃
    std::string s;
	char* className2 = my::GetObjectClassName(&s);
	MyLogD("className2 = %s \n", className2);
}

原理

参考下面的图,表示了RTTI的数据结构
在这里插入图片描述

参考资料

**ps:**文章中内容仅用于技术交流,请勿用于违规违法行为。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜猫逐梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值