C++中四种类型转换方式(ynamic_cast,const_cast,static_cast,reinterpret_cast)

  Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?为什么要注意?
  A:转换的含义是通过改变一个变量的类型为别的类型从而改变该变量的表示方式。为了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符。比如,为了转换一个类型为doubole的浮点数的指针到整型:
代码:
  int i;
  double d;
  i = (int) d;或者:i = int (d);

  对于具有标准定义转换的简单类型而言工作的很好。然而,这样的转换符也能不分皂白的应用于类(class)和类的指针。ANSI-C++标准定义了四个新的转换符:'reinterpret_cast', 'static_cast', 'dynamic_cast' 和 'const_cast',目的在于控制类(class)之间的类型转换。
代码:
  • reinterpret_cast<new_type>(expression)
  • dynamic_cast<new_type>(expression)
  • static_cast<new_type>(expression)
  • const_cast<new_type>(expression)
  1. static_cast:静态类型转换 
  2. const_cast:常量类型转换
  3. dynamic_cast:动态类型转换
  4. reinterpret_cast:重新解释类型转换
1、dynamic_cast运算符
  该转换符用于将一个指向派生类的基类指针或引用转换为派生类的指针或引用
  注意:dynamic_cast转换符只能用于含有虚函数的类,其表达式为 dynamic_cast<类型>(表达式)
  其中的类型是指把表达式要转换成的目标类型,比如含有虚函数的基类B和从基类B派生出的派生类D,则:
  B *pb; 
  D *pd, md;  
  pb = &md; 
  pd = dynamic_cast<D *>(pb); 
  最后一条语句表示把指向派生类D的基类指针pb转换为派生类D的指针,然后将这个指针赋给派生类D的指针pd,有人可能会觉得这样做没有意义,既然指针pd要指向派生类为什么不pd = &md;这样做更直接呢?有些时候我们需要强制转换,比如如果指向派生类的基类指针B想访问派生类D中的除虚函数之外的成员时就需要把该指针转换为指向派生类D的指针,以达到访问派生类D中特有的成员的目的,比如派生类D中含有特有的成员函数g(),这时可以这样来访问该成员dynamic_cast<D *>(pb)->g();因为dynamic_cast转换后的结果是一个指向派生类的指针,所以可以这样访问派生类中特有的成员。但是该语句不影响原来的指针的类型,即基类指针pb仍然是指向基类B的。如果单独使用该指针仍然不能访问派生类中特有的成员。一般情况下不推见这样使用dynamic_cast转换符,因为dynamic_cast的转换并不会总是成功的,具体情况在后面介绍。
 
dynamic_cast的注意事项
  dynamic_cast转换符只能用于指针或者引用。dynamic_cast转换符只能用于含有虚函数的类。dynamic_cast转换操作符在执行类型转换时首先将检查能否成功转换,如果能成功转换则转换之,如果转换失败,如果是指针则反回一个0值,如果是转换的是引用,则抛出一个bad_cast异常,所以在使用dynamic_cast转换之间应使用if语句对其转换成功与否进行测试,比如pd = dynamic_cast(pb); if(pd){…}else{…},或者这样测试if(dynamic_cast(pb)){…}else{…}。
 
  因此,dynamic_cast操作符一次执行两个操作。首先验证被请求的转换是否有效,只有转换有效,操作符才实际进行转换。基类的指针可以赋值为指向派生类的对象,同样,基类的引用也可以用派生类对象初始化,因此,dynamic_cast操作符执行的验证必须在运行时进行。
 
2、const_cast操作符
  其表达式为 const_cast<类型>(表达式)
  其中类型指要把表达式转换为的目标类型。该操作符用于改变const和volatile,const_cast最常用的用途就是删除const属性,如果某个变量在大多数时候是常量,而在某个时候又是需要修改的,这时就可以使用const_cast操作符了。
const_cast操作符不能改变类型的其他方面,他只能改变const或volatile,即const_cast不能把int改变为double,但可以把const int改变为int。const_cast只能用于指针或引用。
const_cast的用法举例
比如:int a=3; const int *b=&a; int* c=const_cast(b); *c=4; cout<<a<<*c;这时输出两个4,如果不使用const_cast转换符则常量指针*c的值是不能改变的,在这里使用const_cast操作符,通过指针b就能改变常量指针和变量a的值。
 
3、static_cast操作符
  该操作符用于非多态类型的转换,任何标准转换都可以使用他,即static_cast可以把int转换为double,但不能把两个不相关的类对象进行转换,比如类A不能转换为一个不相关的类B类型。static_cast本质上是传统c语言强制转换的替代品。
 
  static_cast(静态转换)执行非多态的转换,用于代替C中通常的转换操作。因此,被做为隐式类型转换使用。显式告诉编译器,不关心转换后精度损失。比如:
int i;
float f = 166.7f;
i = static_cast<int>(f);
此时结果,i的值为166。

4.reinterpret_cast

interpret是解释的意思,reinterpret即为重新解释,此标识符的意思即为数据的二进制形式重新解释,但是不改变其值。如:int i; char *ptr="hello freind!"; i=reinterpret_cast<int>(ptr);这个转换方式很少使用。

  reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。

  • 从指针类型到一个足够大的整数类型
  • 从整数类型或者枚举类型到指针类型
  • 从一个指向函数的指针到另一个不同类型的指向函数的指针
  • 从一个指向对象的指针到另一个不同类型的指向对象的指针
  • 从一个指向类函数成员的指针到另一个指向不同类型的函数成员的指针
  • 从一个指向类数据成员的指针到另一个指向不同类型的数据成员的指针
  • //基本类型指针的类型转换

    double d=9.2;

    double* pd = &d;

    int *pi = reinterpret_cast<int*>(pd);  //相当于int *pi = (int*)pd;

    //不相关的类的指针的类型转换

    class A{};

    class B{};

    A* pa = new A;

    B* pb = reinterpret_cast<B*>(pa);   //相当于B* pb = (B*)pa;

posted @ 2014-03-08 13:45  任智康  阅读(504)  评论(0编辑  收藏  举报