1、类型转换
a) dynamic_cast :使得能够在类层次结构中进行向上向下转换(向基类方向转换,is-a关系保证正确性),而不允许其他转换,该转换效率较低。
- dynamic_cast要求类必须有虚函数;
- 一种特殊的特性:把一个指针 dynamic_cast 成 void类型(或 const void或 volatile void* ),生成的指针将指向“原指针指向对象内存”的开始处。
b) const_cast:只能用于去除同类对象的const,violate属性问题,常量变为非常量。
c) static_cast:用于强迫隐式转换,double转int,将非const转为const,以及各种数值转换(程序员保证安全性)。
d) reinterpret_cast:执行低级转型,实际动作(及结果)可能取决于编译器,表示其不可移植性,是危险的动作,比较少见,指针转int等等。
a)dynamic_cast 与static_cast区别:
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
2、运行阶段类型识别(RTTI)
作用:确定基类指针指向的是哪一类对象,以防止调用该类不存在的方法。
注:只适用于包含虚函数的类。
实现方式:
1、dynamic_cast:将基类指针a(指向某一基类或派生类对象)转换为某一派生类B指针。转换成功表明,该指针a指向的对象为该派生类B或该派生类的子类C的对象;失败则返回0(空指针)表明:指针a指向基类A的对象。
2、type_id:返回指向对象类型的值。定义在type_info类中,接受两类参数:类名,对象名。
注:最好使用方式1,因为扩展性强。
例子:
//.h
Class A{
virtual funa();
};
Class B :public A{
virtual funa();
virtual funb();
};
Class C :public B{
virtual funa();
func();
};
//.cpp
A* a1 = new A(); // a1->funb()运行失败。
A* a2 = new B(); // a2->funb()运行成功。
A* a3 = new C();
B* a;
C* x;
实现方式1:dynamic_cast
if(a = dynamic_cast<B*>(a2)){ // 判断a2指向对象类型
// 判断返回值,假如为空指针“0”,则表示false
// 基类指针指向基类对象时不能强转为派生类指针,因为基类没有派生类的特征
a->funb(); //若a指向类A对象,则无此方法,会导致访问失败。
}
if(x = dynamic_cast<C*>(a3)){ // 判断a3指向对象类型
x->func(); //若a3指向类A、B对象,则无此方法,会导致访问失败。
}
实现方式2:type_id
#include<type_info>
if(typeid(C) == typeid(*a3)){ // 两类型匹配则a3指向类型C对象。
a3->func();
}
参考资料:C++ Primer Plus 15.4与15.5节
总结
1、基类指针指向基类对象时不能强转为派生类指针,因为基类不包含派生类的特征。
2、基类指针指向基类对象时不能调用派生类方法,可利用dynamic_cast判断指针指向的对象。
3、C++中类型转换方式如上所示。