C++学习笔记13
1. const_cast (expr)
const_cast 运算符用于修改类型的 const / volatile 属性。除了 const 或 volatile 属性之外,目标类型必须与源类型相同。这种类型的转换主要是用来操作所传对象的 const 属性,可以加上 const 属性,也可以去掉 const 属性。
class A { // … };
void Function()
{
const A *pConstObj = new A;
A *pObj = pConstObj; //ERROR: 不能将const对象指针赋值给非const对象
pObj = const_cast<A*>( pConstObj); // OK
//...
}
2. dynamic_cast (expr)
dynamic_cast 在运行时执行转换,验证转换的有效性。如果转换未执行,则转换失败,表达式 expr 被判定为 null。dynamic_cast 执行动态转换时,type 必须是类的指针、类的引用或者 void*,如果 type 是类指针类型,那么 expr 也必须是一个指针,如果 type 是一个引用,那个 expr 也必须是一个引用。它将expr值转换成类型为type的对象指针,主要用来实现类层次结构的提升,在很多书中它被称做“安全的向下转型(Safe Downcasting)”,用于继承体系中的向下转型,将基类指针转换为派生类指针,这种转换较为严格和安全。如下面的代码片段所示:
class B { //... };
class D : public B { //... };
void Function(B *pObjB)
{
D *pObj = dynamic_cast<D*>( pObjB);
//...
}
如果pObjB指向一个D类型的对象,pObj则指向该对象,所以对该指针执行D类型的任何操作都是安全的。但是,如果pObjB指向的是一个B类型的对象,pObj将是一个空指针,这在一定程度上保证了程序员所需要的“安全”,只是,它也付出了一定的运行时代价,而且代价非常大,实现相当慢。有一种通用实现是通过对类名称进行字符串比较来实现的,只是其在继承体系中所处的位置越深,对strcmp的调用就越多,代价也就越大。如果应用对性能要求较高,那么请放弃dynamic_cast。
3. reinterpret_cast (expr)
reinterpret_cast 运算符把某种指针改为其他类型的指针。它可以把一个指针转换为一个整数,也可以把一个整数转换为一个指针。
class A { // ... };
class B { //... };
void f()
{
A* pa = new A;
B* pb = reinterpret_cast<B*>(pa);
// ...
}
4. static_cast (expr)
static_cast 运算符执行非动态转换,没有运行时类检查来保证转换的安全性。例如,它可以用来把一个基类指针转换为派生类指针。
class B { ... };
class D : public B { ... };
void Function(B* pb, D* pd)
{
D* pd2 = static_cast<D*>(pb); // 不安全
B* pb2 = static_cast<B*>(pd); // 安全的
}
之所以说第一种是不安全的,是因为如果pb指向的仅仅是一个基类B的对象,那么就会凭空生成继承信息。至于这些信息是什么、正确与否,无从得知。所以对它进行D类型的操作将是不安全的。