当前位置: 首页 > article >正文

C++不同平台下的RTTI实现

给定一个含有虚函数的对象的地址,找到对应的类名,不同平台下方法也不同,这是由于RTTI实现并没有统一的标准。

Linux:

Linux

#include <iostream>
#include <typeinfo>

class Person
{
public:
    virtual void func()
    {
        std::cout << typeid(*this).name() << std::endl;
    }
};

const char* ClassName(void* address)
{
    uintptr_t* objPtr = reinterpret_cast<uintptr_t*>(address);
    uintptr_t* vftablePtr = reinterpret_cast<uintptr_t*>(*objPtr);
    std::type_info* ti = reinterpret_cast<std::type_info*>(*(vftablePtr - 1));
    return ti->name();
}

int main()
{
    Person p;
    std::cout << ClassName(&p) << std::endl;
    std::cout << typeid(p).name() << std::endl;
}

运行结果:

6Person
6Person

其中,Person代表类名,6表示的是类名的长度。


Windows x86:

Windows x86

#include <iostream>
#include <typeinfo>

class Person
{
public:
    virtual void func()
    {
        std::cout << typeid(*this).name() << std::endl;
    }
};

const char* ClassMangledName(void* address)
{
    uintptr_t* objPtr = reinterpret_cast<uintptr_t*>(address);
    uintptr_t* vftablePtr = reinterpret_cast<uintptr_t*>(*objPtr);
    uintptr_t* rttiObject = reinterpret_cast<uintptr_t*>(*(vftablePtr - 1));
    std::type_info* ti = reinterpret_cast<std::type_info*>(*(rttiObject + 3));

    const char* className = ti->name();
    return className;
}

int main()
{
    Person p;
    std::cout << ClassMangledName(&p) << std::endl;
    std::cout << typeid(p).name() << std::endl;
}

运行结果:

class Person
class Person

Windows x64:

Windows x64

#include <iostream>
#include <ehdata.h>
#include <rttidata.h>

class Person
{
public:
    virtual void func()
    {
        std::cout << typeid(*this).name() << std::endl;
    }
};

const char* ClassMangledName(void* address)
{
    uintptr_t* objPtr = reinterpret_cast<uintptr_t*>(address);
    uintptr_t* vftablePtr = reinterpret_cast<uintptr_t*>(*objPtr);
    _RTTICompleteObjectLocator* rttiLocator = reinterpret_cast<_RTTICompleteObjectLocator*>(*(vftablePtr - 1));
    uintptr_t imageBase = reinterpret_cast<uintptr_t>(rttiLocator) - rttiLocator->pSelf;
    TypeDescriptor* typeDescriptor = reinterpret_cast<TypeDescriptor*>(imageBase + rttiLocator->pTypeDescriptor);

    const char* classMangledName = typeDescriptor->name;
    return classMangledName;
}

int main()
{
    Person p;
    std::cout << ClassMangledName(&p) << std::endl;
    std::cout << typeid(p).raw_name() << std::endl;
}

运行结果:

.?AVPerson@@
.?AVPerson@@

打印的结果是raw name,也就是未修饰的名字。


http://www.kler.cn/a/147855.html

相关文章:

  • 基于ECS实例搭建Hadoop环境
  • 苦等三年!金克斯大人回来了!
  • 【C#设计模式(4)——构建者模式(Builder Pattern)】
  • Linux—进程学习-02
  • 985研一学习日记 - 2024.11.14
  • 2023年MathorCup数学建模B题城市轨道交通列车时刻表优化问题解题全过程文档加程序
  • 云服务器:未来的计算力量
  • 如何解决中小制造业企业信息化难题?
  • Visual Studio(VS) C++程序LNK2005错误,提示“error LNK2005: _XXX已经在xxx.obj中定义”解决方案
  • Pangolin报错
  • 详解HTTP协议(介绍--版本--工作过程--Fiddler 抓包显示--请求响应讲解)
  • windows安装 evo
  • hadoop集群环境搭建和常用命令
  • 9.Spring 整合 Redis
  • Dockerfile讲解
  • HCIP-九、路由控制
  • Netty实现websocket且实现url传参的两种方式(源码分析)
  • 揭秘论文开题报告写作技巧,全程无忧,附赠技术路线图模板!
  • 解决electron-build打包后运行app报错:cannot find module xxx
  • 汽车功能安全ISO26262
  • VC++、MFC中操作excel时,Range.Cells和Worksheet.Cells的区别是什么?
  • VSCode:修改左侧窗口字体大小
  • Java版企业电子招标采购系统源码—企业战略布局下的采购寻源
  • 【链接MySQL】教你用VBA链接MySQL数据库
  • Java核心知识点整理大全20-笔记
  • pgsql 时区查看和修改