C++ 通过运行时类型识别 RTTI(转)

RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类指针或引用来检查这些指针或引用所指的对象的实际派生类型。
RTTI提供了以下两个非常有用的操作符:
(1)typeid操作符,返回指针和引用所指的实际类型。
(2)dynamic_cast操作符,将基类类型的指针或引用安全地转换为派生类型的指针或引用。
 
typeid操纵符会返回一个type_info类,这个类有一个成员函数是name()得到类型名,type_info类构造方法私有,只能由typeid产生,type_info重载了== 和!= ,隐藏了赋值运算符=,所以可以用来比较两个变量的类型是否相等和不等,但不能赋值。
使用 :type_info x = typeid(对象引用);
typeid实现的原理是使用了友元函数,typeid作为type_info类的友元函数,可以调用私有的构造方法产生type_info对象
typeid接受的参数是引用,如果传一个A类型的指针,并且指针指向的是A的子类的对象,但typeid返回的依然是对象A的type_info,只有将传*p才是代表真正的A的子类的对象,这时才会返回A的子类的type_info
 
dynamic_cast操作符只能转换含有虚函数的类,语法为dynamic_cast<类型>(表达式),在C++中,向上转换不需要强制转换,比如有一个父类的指针p, p =new 子类(); 这样不会错,但是有子类的指针cp, cp = p 就不行了,必须用dynamic_cast 进行转换。dynamic_cast 转换失败返回null。
 
后序补全const_cast,static_cast,reinterpret_cast

const_cast

 
用法:const_cast<type_id> (expression)
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
一、常量指针被转化成非常量的指针,并且仍然指向原来的对象;
二、常量引用被转换成非常量的引用,并且仍然指向原来的对象;
void foo()
{
const B b1;
//b1.m_iNum = 100; //compile error
/* 可以做如下转换,体现出转换为指针类型 */
B *b2 = const_cast<B*>(&b1);
/* 或者左侧也可以用引用类型,如果对b3或b4的数据成员做改变,就是对b1的值在做改变 */
B &b3 = const_cast<B&>(b1);
b2 -> m_iNum = 200; //fine
b3.m_iNum = 300;//fine
}
 

static_cast

 
用法:static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性。
 
reinterpret_cast[1]是C++里的强制类型转换符。
操作符修改了操作数类型,但仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换
 
static_cast在转换的时候会把数据的二进制进行重新解析,比如float f = 1.333 ,int i = static_cast<int>(f)
i的值为1
reinterpret_cast 则不会重新解析,只会把二进制的值直接赋予给i。
原文地址:https://www.cnblogs.com/cplover/p/3371954.html