C++中的类型转换:static_cast/dynamic_cast/const_cast/reinterpet_cast

  • static_cast
    • static_cast<type_id>(expression),使用type_id将expression类型转换
    • static_cast 运算符可用于将指向基类的指针转换为指向派生类的指针等操作。 此类转换并非始终安全。
    • 通常使用 static_cast 转换数值数据类型,例如将枚举型转换为整型或将整型转换为浮点型,而且你能确定参与转换的数据类型
    • static_cast 转换安全性不如 dynamic_cast 转换,因为 static_cast 不执行运行时类型检查,而 dynamic_cast 执行该检查。 对不明确的指针的 dynamic_cast 将失败,而 static_cast 的返回结果看似没有问题,这是危险的。
// static_cast_Operator.cpp
// compile with: /LD
class B {};
class D : public B {};
void f(B* pb, D* pd) {
   D* pd2 = static_cast<D*>(pb);   // Not safe, D can have fields
                                   // and methods that are not in B.
   B* pb2 = static_cast<B*>(pd);   // Safe conversion, D always
                                   // contains all of B.
}
  • 与 dynamic_cast 不同,pb 的 static_cast 转换不执行运行时检查。 由 pb 指向的对象可能不是 D 类型的对象,在这种情况下使用 *pd2 会是灾难性的。 例如,调用 D 类(而非 B 类)的成员函数可能会导致访问冲突。
  • 该行为也适用于类以外的类型。 例如,static_cast 可用于将 int 转换为 char。 但是,得到的 char 可能没有足够的位来保存整个 int 值。 同样,这需要程序员来验证 static_cast 转换的结果是否安全。
  • static_cast 运算符可以将整数值显式转换为枚举类型。 如果整型值不在枚举值的范围内,生成的枚举值是不确定的。
  • static_cast 运算符将 null 指针值转换为目标类型的 null 指针值。
  • 任何表达式都可以通过 static_cast 运算符显式转换为 void 类型。 目标 void 类型可以选择性地包含 const、volatile 或 __unaligned 特性。
  • static_cast 运算符无法转换掉 const、volatile 或 __unaligned 特性。 有关移除这些特性的详细信息,请参阅 const_cast Operator。
  • dynamic_cast
    • dynamic_cast<type_id>(expression)
    • dynamic_cast 常用语不需要引起异常,而是把转换失败当做一个普通操作的情况。Use dynamic_cast when you cast an object (more specifically, a hat ^) to a more derived type, you expect either that the target object might sometimes be nullptr or that the cast might fail, and you want to handle that condition as a regular code path instead of an exception.
    • type-id 必须是一个指针或引用到以前已定义的类类型的引用或“指向 void 的指针”。 如果 type-id 是指针,则expression 的类型必须是指针,如果 type-id 是引用,则为左值。
    • 如果 type-id 为 void*,则做运行时进行检查确定 expression的实际类型。 结果是指向 by expression 的完整的对象的指针。 例如:
// dynamic_cast_2.cpp
// compile with: /c /GR
class A {virtual void f();};
class B {virtual void f();};

void f() {
   A* pa = new A;
   B* pb = new B;
   void* pv = dynamic_cast<void*>(pa);
   // pv now points to an object of type A

   pv = dynamic_cast<void*>(pb);
   // pv now points to an object of type B
}
  • 如果 type-id 不是 void*,则做运行时进行检查以确定是否由 expression 指向的对象可以转换为由 type-id指向的类型。如果失败了,则返回nullptr
  • “向上转换”,如果 type-id 是指向 expression的明确的可访问的直接或间接基类的指针,则结果是指向 type-id 类型的唯一子对象的指针。因为它将在类层次结构上的指针,从派生的类移到该类派生的类。 向上转换是一种隐式转换。
// dynamic_cast_1.cpp
// compile with: /c
class B { };
class C : public B { };
class D : public C { };

void f(D* pd) {
   C* pc = dynamic_cast<C*>(pd);   // ok: C is a direct base class
                                   // pc points to C subobject of pd 
   B* pb = dynamic_cast<B*>(pd);   // ok: B is an indirect base class
                                   // pb points to B subobject of pd
}
  • “向下转换”,如果 expression 类型是 type-id类型的基类,则做运行时检查来看是否 expression 确实指向 type-id类型的完整对象。 如果为 true,则结果是指向 type-id类型的完整对象的指针。因为它将在类层次结构下的指针,从给定的类移到该类派生的类。
// dynamic_cast_3.cpp
// compile with: /c /GR
class B {virtual void f();};
class D : public B {virtual void f();};

void f() {
   B* pb = new D;   // unclear but ok
   B* pb2 = new B;

   D* pd = dynamic_cast<D*>(pb);   // ok: pb actually points to a D
   D* pd2 = dynamic_cast<D*>(pb2);   // pb2 points to a B not a D
}
  • reinterpret_cast
    • reinterpret_cast < type-id > ( expression )
    • Allows any pointer to be converted into any other pointer type
    • Allows any integral type to be converted into any pointer type
    • When the cast is invalid, reinterpret_cast might return a non-null value, it is dangerous
    • On the contrary, dynamic_cast will return nullptr when the cast is invalid
    • The reinterpret_cast allows the pointer to be treated as an integral type.
  • const_cast
    • const_cast (expression)
    • Removes the const, volatile, and __unaligned attribute(s) from a class
    • The const_cast operator converts a null pointer value to the null pointer value of the destination type.
    • You cannot use the const_cast operator to directly override a constant variable’s constant status.
    • const_cast转换后的结果仍然指向原对象。根据被转换对象的类型不同,转换后的写操作可能引起位置的行为。For pointers and references, the result will refer to the original object. For pointers to data members, the result will refer to the same member as the original (uncast) pointer to data member. Depending on the type of the referenced object, a write operation through the resulting pointer, reference, or pointer to data member might produce undefined behavior.
    • const_cast仅在其位于的那句语句中生效,下一条语句后,原const对象还是const属性。The cast lasts only for the remainder of the statement in which it appears.
    • const_cast的目的不是改变一个具有const属性的对象由const变为非const,而是修改指针或引用的权限。如果指针或引用的对象是const属性,那么转换后的行为是未定义的
    • 那么const_cast用在何处呢?举例:一个原本不带const属性的对象,需要作为const的函数形参
// expre_const_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class CCTest {
public:
   void setNumber( int );
   void printNumber() const;
private:
   int number;
};

void CCTest::setNumber( int num ) { number = num; }

void CCTest::printNumber() const {
   cout << "\nBefore: " << number;
   const_cast< CCTest * >( this )->number--;    //const_cast仅在当前语句中生效
   cout << "\nAfter: " << number;
}

int main() {
   CCTest X;
   X.setNumber( 8 );
   X.printNumber();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值