RTTI运行时类型识别
RTTI 运行时类型识别
-
根据基类的指针或引用来获得该指针或引用所指的对象的实际类型
-
通过typeid操作符识别出所有的基本类型的变量对应的类型
当typeid
中的操作数是以下任意一种时,typeid
需要在程序运行时推算类型,因为其操作数的类型在编译时期是不能被确定的:
- 一个指向含有多态的类对象的指针的解引用
- 一个指向含有多态的类对象的引用
#include <iostream>
#include <string>
#include <vector>
#include <typeinfo>
#include <cxxabi.h>
const char* TypeToName(const char* name)
{
const char* __name = abi::__cxa_demangle(name, nullptr, nullptr, nullptr);
return __name;
}
// 单纯虚继承是无法体现出多态的,尽管它也会生成对应的虚表,要真正实现多态只能依靠虚函数来实现
class A
{
public:
void print()
{
std::cout << "A" << std::endl;
}
int a;
};
class B : virtual public A
{
public:
void print()
{
std::cout << "B" << std::endl;
}
int b;
};
class C : virtual public A
{
public:
void print()
{
std::cout << "C" << std::endl;
}
int c;
};
class D : public B, public C
{
public:
void print()
{
std::cout << "D" << std::endl;
}
int d;
};
int main(int argc, char* argv[])
{
D d;
A* a_ptr = &d;
B* b_ptr = &d;
C* c_ptr = &d;
std::cout << TypeToName(typeid(d).name()) << std::endl;
std::cout << TypeToName(typeid(*a_ptr).name()) << std::endl;
std::cout << TypeToName(typeid(*b_ptr).name()) << std::endl;
std::cout << TypeToName(typeid(*c_ptr).name()) << std::endl;
}
手动实现
long long* vtbl_A = (long long*)*(long long*)a_ptr;
std::cout << ((std::type_info*)*(vtbl_A - 1))->name() << std::endl << std::endl;