0. dynamic_cast
dynamic_cast
是实现 运行时类型识别(run-time type identification, RTTI)功能的方法之一,另一个是typeid。
dynamic_cast
同时也是显示类型转换的功能之一,主要解决的就是具有继承关系的子类和父类间的转换。
1 具体功能
1.1 使用方法
dynamic_cast
主要有3种形式:
1. dynamic_cast<type *>(expr) // 指针
2. dynamic_cast<type &>(expr) // 左值引用
3. dynamic_cast<type &&>(expr) // 右值引用
3种形式中所有的type
必须是类类型 且应该 含有虚函数。
3种形式对应的硬性要求分别是:
- 指针必须有效
- expr必须是左值
- expr不能是左值
满足任一以下条件,转换成功:
- expr是type类型的公有派生类
- expr是type类型的公有基类
- expr是type类型本身
否则转换失败。
失败时:
- 指针返回0
- 引用抛出
bad_cast
异常
使用dynamic_cast
最好进行if判断和异常获取,如下面的指针和引用的例子。
1.2 指针
Derived d;
Base *base_ptr = &d;
if (Derived *derived_ptr = dynamic_cast<Derived *>(base_ptr)) {
cout << "cast succeed" << endl;
derived_ptr->func();
} else {
cout << "cast failed" << endl;
base_ptr->func();
}
程序将会输出cast succeed。
1.3 引用
Derived d;
Base &base_ref = d;
try {
auto &derived_ref = dynamic_cast<Derived &>(base_ref);
cout << "cast succeed" << endl;
derived_ref.func();
} catch (bad_cast) {
cout << "cast failed" << endl;
base_ref.func();
}
程序将会输出cast succeed。
1.4 不会取消const
转换过程中会保留expr的const信息,例如:
Derived d;
// 与上面示例不一样
const Base &base_ref = d;
try {
// ERROR: 编译不能通过
auto &derived_ref = dynamic_cast<Derived &>(base_ref);
cout << "cast succeed" << endl;
derived_ref.func();
} catch (bad_cast) {
cout << "cast failed" << endl;
base_ref.func();
}
编译报错。
指针同理,如果指针具有底层const,则会报错。