一:RTTI
RTTI:Run Time Type Identification,运行时类型识别。
通过RTTI,程序能够使用基类的指针或者引用来检查这些指针或者引用所指的对象的实际派生类型。
理解:RTTI我们可以把这个称呼看成是一种系统提供给我们的一种能力,或者一种功能。
这种功能或者能力是通过两个运算符来体现的。
(1)dynamic_cast运算符,能够将基类的指针或者引用安全的转换为派生类的指针或者引用。
(2)typeid运算符,返回指针或者引用所指对象的实际类型。
说明:要想让RTTI工作,则父类当中必须要有虚函数。
RTTI实现原理
vs2019测试
class A
{
public:A() {
};virtual ~A() {
}int a;
};A* obj = new A();
long* p1 = (long*)obj;
long* p2 = (long *)*p1;
long* p3 = (long *)(*(p2 - 1));
long* p4 = (long*)(*(p3 + 3));
const std::type_info* p5 = (const std::type_info *) p4;
cout << p5->name() << endl; //class A
二:type_info类与dynamic_cast运算符
(1)dynamic_cast运算符
class A
{
public:A() {
};virtual ~A() {
}
};class B :public A
{
public:void aaa() {
}
};A* a = new B();
B* obj = dynamic_cast<B*>(a);
if (obj != nullptr)
{
printf("转换成功");
}
else
{
printf("转换失败");
}/*引用方面的转换*/
A& q = *a;
try
{
B& b = dynamic_cast<B &> (q);printf("转换成功");
}
catch (std::bad_cast)
{
/**/printf("转换失败");
}//转换成功了,我们就可以调用类B里面定义的函数了,不然的话,虽然new的是B,但是,还是会调用不了类B里面的非虚函数,所以说,既不想把函数声明成虚函数的话,但是又想调用类B的函数的话,就需要dynamic_cast运算符运算符了。
(2)typeid运算符
#include <iostream>
#include <string>
using namespace std;
class A {
public:int a;virtual void bb(){
}
};
class B:public A {
public:void b(){
}
};
int main()
{
//typeid运算符//typeid(表达式) typeid(类型) A obj;std::cout << typeid("a").name() << std::endl;std::cout << typeid(obj).name() << std::endl;std::cout << typeid(int).name() << std::endl;A* p = new B();A* q = new A();//比较指针的类型是否相同,if (typeid(p) == typeid(q)) {
std::cout << "p和q的静态类型相同" << std::endl;}if (typeid(*p) == typeid(*q)) {
std::cout << "p和q的动态类型相同" << std::endl;}return 0;
}
(2)type_info类
#include <iostream>
#include <string>
using namespace std;
class A {
public:int a;virtual void bb(){
}
};
class B:public A {
public:void b(){
}
};int main()
{
//typeid,返回的是一个常量对象的引用,这个常量对象是标准库当中的type_info类A* p = new B();A* q = new B();const std::type_info& tp = typeid(*p);const std::type_info& tp1 = typeid(*q);//有虚函数,所以类型是B,如果没有虚寒苏,类型就是Astd::cout << tp.name() << std::endl;//type_info还支持类型比较if (tp == tp1) {
std::cout << "tp和tp1的动态类型相同" << std::endl;}return 0;
}