一、dynamic_cast
使用dynamic_cast
一个继承层次内进行转化的指针/引用。dynamic_cast依赖于RTTI信息,在转换时,dynamic_cast会检查转换的source对象是否真的可以转换成target类型,这种检查不是语法上的,而是真实情况的检查。被转换的类型必须是多态(即有虚函数)。使用这个会影响运行效率,一般情况下也是不使用的。能在编译时解决掉的问题没必要留到运行时、能用多态搞定的事情也没必要使用 dynamic_cast 和 typeid 等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
if (pb2) {
}
|
在上面的代码段中,如果 pb 指向一个 D 类型的对象,pd1 和 pd2 是一样的,并且对这两个指针执行 D 类型的任何操作都是安全的;但是,如果 pb 指向的是一个 B 类型的对象,那么 pd1 将是一个指向该对象的指针,对它进行 D 类型的操作将是不安全的(如访问 m_szName),而 pd2 将是一个空指针。
另外要注意:B 要有虚函数,否则会编译出错;static_cast则没有这个限制。
二、static_cast
使用static_cast
普通类型转换。
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。这种不加static_cast进行转换,一般编译器会提示告警,加static_cast可以消除告警提示。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
三、reinterpret_cast
使用reinterpret_cast
的位模式的低级别重读。使用时要格外小心。reinterpret_cast与编译器平台相关,因此不具有移植性,使用范围也有限。
四、const_cast
使用const_cast
铸造远const/volatile
。除非你使用const不正确的API,否则请避免这种情况。一般就是别人的库API里,但我们要传入的参数是const类型,而库的API要的参数没要求const,这里编译器就会报错,并且我们知道库API那个函数不会修改我们代入的参数,这里就可以用const_cast来处理,避免编译器编译不过。
五、typeid 打印对象名称
BaseA* pa;
BaseA baseA;
pa = &baseA;
cout << “baseA” << " " << typeid(baseA).name() << endl;
cout << “pa” << " " << typeid(pa).name() << endl;
六、typeof
typeof()关键字常见用法一共有以下几种。
-
不用知道函数返回什么类型,可以使用typeof()定义一个用于接收该函数返回值的变量
typeof(fun()) r1;//定义一个变量r1,用于接收函数fun()返回的值,假如我们不知道fun()返回类型也可以这样用
2.在宏定义中动态获取相关结构体成员的类型
#define swap(x,y) \
{ typeof(x) temp; \ -->根据类型定义一个临时变量temp
temp = x;\
x = y;\
y = temp;\
}
3. 做类型转换时的对象类型声明
const PROTOCOL_FORMAT::SPacketHead * pHead = (typeof(pHead)) rPackRecv.getHeadData();
参考:https://www.zhihu.com/question/22445339