操作符 |
中文名称 |
含义 |
dynamic_cast |
动态类型转换符 |
支持多态而存在, 主要用于类之间的转换 |
static_cast |
静态类型转换符 |
仅仅完成编译时期的转换检查 |
reinterpret_cast |
再解释类型转换符 |
完成不同类型指针之间的相互转换 |
const_cast |
常类型转换符 |
用来修改类型的 const 或 volatile 属性 |
1. 动态类型转换符 dynamic_cast
dynamic_cast 为支持多态而存在, 它主要用于类之间的转换, 包括向下转换(downcast)和向上转换(upcast). 向下转换即将一个指向基类的指针或引用转换成一个指向派生类的指针或引用. 如:
void CMyMenu::UpdateMenu(CMenu* pmenu)
{
CMyMenu* psubmenu = dynamic_cast<CMyMenu*>(pmenu);
...
}
当使用 dynamic_cast 尝试进行指针的非法转换时, 指针的值会被赋成 0 . 当这个非法转换是针对引用而进行时, C++ 会抛出一个 bad_cast 异常来通知这个错误.
2. 静态类型转换符 static_cast
静态类型转换仅仅完成编译时期的转换检查. 一般用于如下场合:
(1) 用于类层次结构中基类和子类之间指针或引用的转换. 进行向上转换(把子类的指针或引用转换成基类表示)是安全的(向上转换一般都是隐式转换, 这时候实际上根本没必要使用静态类型转换); 进行向下转换(把基类指针或引用转换成子类表示)时, 由于没有动态类型检查, 所以是不安全的.
(2) 完成任何类型的指针与 void* 之间的转换.
(3) 将空指针(0)转换成目标指针类型.
(4) 用于基本数据类型之间的转换, 如把 int 转换成 char , 把 int 转换成 enum . 这种转换的安全性要由程序员来保证.
3. 再解释类型转换符 reinterpret_cast
再解释类型转换完成的都是一些不可思议的类型转换. 实际上, 所有指针的值都是一个表示地址的数值, 值本身的转换没有任何问题. 所谓"再解释", 是指对指针的类型(如: int* 和 double*)进行重新解释.
再解释类型转换 reinterpret_cast 完成不同类型指针之间的相互转换, 同时也支持将指针与数字之间的转换. 如:
void CMyList::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
...
}
该段代码在 MFC 源码中比较常见, 它将 NMHDR 指针重新解释成 NMLVCUSTOMDRAW 指针.
4. 常类型转换符 const_cast
常类型转换 const_cast 用来修改类型的 const 或 volatile 属性. 除了 const 或 volatile 修饰之外, 其操作对象的类型和目标类型必须是一样的.
5. 向上转换与向下转换
向上转换(upcast, 派生类转换成基类)总是隐含地进行, 派生类总是能够转换成基类的引用类型. 如:
CDialog dlg;
CButton btn;
CWnd& wnd1 = dlg;
CWnd& wnd2 = btn;
有时候, 可能已经知道当前指针所指向的对象到底是什么类型, 那么可以使用强制转换完成向下转换(downcast):
CDialog& dlg2 = (CDialog&)wnd1;
CButton& btn2 = (CButton&)wnd2;
向下转换必须是以显示的方式向编译器提出, 当然, 向下转换具有一定的风险, 如果给定的基类指针并非指向一个派生类对象, 那么, 将它强制进行向下转换, 其结果是不可预料的. 如:
CDialog& dlg2 = (CDialog&)wnd2;
dlg2.DoModal();
这样的代码肯定会报错. 因为 wnd2 其实是一个按钮对象.
【摘自】白乔, 左飞 《把脉VC++》P162~163.