C++转型
内容来自《21天C++》和《efective c++》
c风格的类型转换
char * pszString = "hello world!";
int* pBuf = (int *)pszString;
c风格的类型转换实际上是强迫编译器根据程序员的选择来解释目标对象
C++提供了一种新的类型转换运算符,专门用于继承的情形,这种情形在c中并不存在
4个类型转换运算符如下:
- const_cast 通常用来将对象的常量性转除(cast away the constness)。它是唯一有此能力的C++-style转型操作符。
- dynamic_cast用来执行继承体系中安全的向下转型或跨系转型动作。也就是说你可以利用它将指向基类对象的指针或者引用转型为指向派生类对象的指针或引用,并得知转型是否成功。如果转型失败,会以一个null指针(当转型对象是指针)或一个exception(当转型对象是引用)表现出来。dynamic_cast是唯一无法由旧式语法执行的转型动作,也是唯一可能消耗重大运行成本的转型动作。
- static_cast 基本上拥有与C旧式转型相同的威力与意义,以及相同的限制。例如将一个非 const 的对象转换为 const 对象,或将int 转换为 double等等。它也可以用来执行上述多种转换的反向转换,例如将void*指针转为typed指针,将pointer-to-base转为pointer-to-derived。但是他无法将const转为non-const,这个只有const-cast才能够办到。
- reinterpret_cast意图执行低级转型,实际动作及结果可能取决于编译器,这也就表示它不可移植。例如将一个pointer to int 转型为int。这一类转型在低级代码以外很少见。
应用举例:
static_cast
CBase* pBase = new CDerived(); CDerived *pDerived = static_cast<CDerived*>(pBase); CUnrelated* pUnrelated = static_cast<CUnrelated *>(pBase);//static_cast实现了基本的编译阶段检查,确保指针被转换为相关的类型,该转换编译器会发出错误dynamic_cast与静态类型转换相反,转换在运行阶段,可检查dynamic_cast的操作结果以判断类型的转换成功
CBase* pBase = new CDerived(); CDerived* pDerived = dynamic_cast<CDerived*>(pBase); if(pDerived)pDerived->CallDerivedClassFunction();//检查类型是否转换成功reinterpret_cast是与c风格的转换最为接近的类型转换运算符,它让程序员能够将一种类型转换为另一种类型,不管他们是否相关,所以要尽量避免使用,避免产生类型的不安全
举例:
#include <iostream> using namespace std; class A { public: A(){ma = 1;mb = 2;} void fun(){ printf("%d,%d",ma,mb);} private: int ma; int mb; }; class B{ public: B(){ mc = 3;} void fun(){printf("%d",mc);} private: int mc; }; int main() { A a; A *pa = &a; B *pb = reinterpret_cast<B *>(pa);//有的题目这里为:B *p = (*)(&a); 两个不想关的类指针的转换 pb->fun();//结果输出1,pb指向对象的首地址,fun来打印mc,mc距离对象的首地址的偏移为0,于是打印了对象a首地址偏移为0的值,即为ma的值 system("pause"); return 0; }const_cast去除常量性,
CSomeClass { public: void DisplayMembers();//应该为const但确不是,假设CSomeClass归第三方库所有,你无法修改这时候const_cast就用上了 } void DisplayAllData(const CSomeClass& mData) { CSomeClass& refData = const_cast<CSomeClass&>(mData);//先去除常量性 mData.DisplayMembers(); }