一,RTTI的作用:
.如果我们有一个基类派生了多个子类而又有很多虚函数,通过某个基类指针完成对对象的调用,有时候为了将这种对象赋值给基类指针这种操作的合法性;或者处于调试目的需要知道两种类型是否一致。
二,RTTI的三个元素:
1,dynamic_cast
用法:适用于向上转换才合法,也就是说派生类的对象赋值给基类指针,而不能基类对象赋给派生类,安全性转换的检查操作(派生类扩充后调用函数基类可能没有这个成员函数)
eg:
class A{ //有虚函数};
classB :public A{...};
class C:public B{...};
有下面的指针:
A *pa=new A;
B* pb=new B;
C* pc=new C;
有下面的操作转换:
C *p1=(C*)pc;//#1
C* p2=C* pa; //#2
显然#2是不合法的,因为他尝试向上转换;
语法: A 星pa=danamic_cast<A*>(pc); 是否能安全的转换为A*?如果可以返回对象的地址,否则返回其空指针;
2,typeid运算符:判断两种对象是否为同一类型;
用法:typeid返回对type_info对象的引用;并且type_info类重载了==和!=运算符;
typeid(A)==typeid(*pa);
如果pa为空指针将引发bad_typeid异常,需在#include申明,type_info类有一个name()成员通常返回类的名称;
cout<<“该类的名称:”<<typeid(*pa).name();
总结:RTTI必须用于继承关系且包含虚函数;如果大量的使用了if else 且用了typeid;则考虑使用虚函数重写和danamic_cast;
三,类型转换运算符:
1,dynamic_cast;(向上转换):
A 星pa=danamic_cast<A*>(pc)//#1
2,const_cast;(修改const或volatile的特征)
const_cast<类名a>(表达式b);注意a与b必须是同类型;
void change(const int * pt)
{
int *pc=const _cast<int*>(pt);//让pt此时const int * pt变为int *pt
*pc=20;
}
int po=100;
change(&po);
/如果po为const,change()的修改会失效,反之成功;
3,
static_cast(隐式转换,向上向下转换都可以)
const_cast<类名a>(表达式b);注意a与b必须可以一方到另外一方的隐式转换;
包括:a,b是继承关系,或者double转int,float转long等各种数值隐式转换;
4,reiterpret_cast(几乎没用,用c的强制转换代替)