c++类型转换

C++中类型转换运算符


C++的四个类型转换运算符已经有很久了,但一直没有弄清楚它们的用法,今天看到一本书上的解释,才大致地的了解了其具体的用法.

具体归纳如下:

reinterpret_cast

函数将一个类型的指针转换为另一个类型的指针.

这种转换不用修改指针变量值存放格式(不改变指针变量值),只需在编译时重新解释指针的类型就可做到.reinterpret_cast 可以将指针值转换为一个整型数,但不能用于非指针类型的转换.

例:

 
  1. //基本类型指针的类型转换  
  2. double d=9.2;  
  3. doublepd &d;  
  4. int *pi reinterpret_cast<int*>(pd); //相当于int *pi (int*)pd;  
  5. //不相关的类的指针的类型转换  
  6. class A{};  
  7. class B{};  
  8. A* pa new A;  
  9. B* pb reinterpret_cast<B*>(pa); //相当于B* pb (B*)pa;  
  10. //指针转换为整数  
  11. long reinterpret_cast<long>(pi); //相当于long (long)pi; 

const_cast

该函数用于去除指针变量的常量属性,将它转换为一个对应指针类型的普通变量。反过来,也可以将一个非常量的指针变量转换为一个常指针变量。

这种转换是在编译期间做出的类型更改。

例:

 
  1. const intpci 0;  
  2. intpk const_cast<int*>(pci); //相当于int* pk (int*)pci;  
  3. const A* pca new A;  
  4. A* pa const_cast<A*>(pca); //相当于A* pa (A*)pca; 

出于安全性考虑,const_cast无法将非指针的常量转换为普通变量。

static_cast

该函数主要用于基本类型之间和具有继承关系的类型之间的转换。

这种转换一般会更改变量的内部表示方式,因此,static_cast应用于指针类型转换没有太大意义。

例:

 
  1. //基本类型转换  
  2. int i=0;  
  3. double static_cast<double>(i); //相当于 double (double)i;  
  4. //转换继承类的对象为基类对象  
  5. class Base{};  
  6. class Derived public Base{};  
  7. Derived d;  
  8. Base static_cast<Base>(d); //相当于 Base (Base)d; 

dynamic_cast

它与static_cast相对,是动态转换。

这种转换是在运行时进行转换分析的,并非在编译时进行,明显区别于上面三个类型转换操作。

该函数只能在继承类对象的指针之间或引用之间进行类型转换。进行转换时,会根据当前运行时类型信息,判断类型对象之间的转换是否合法。dynamic_cast的指针转换失败,可通过是否为null检测,引用转换失败则抛出一个bad_cast异常。

例:

 
  1. class Base{};  
  2. class Derived public Base{};  
  3. //派生类指针转换为基类指针  
  4. Derived *pd new Derived;  
  5. Base *pb dynamic_cast<Base*>(pd);  
  6. if (!pb)  
  7. cout << "类型转换失败" << endl;  
  8. //没有继承关系,但被转换类有虚函数  
  9. class A(virtual ~A();) //有虚函数  
  10. class B{}:  
  11. A* pa new A;  
  12. B* pb dynamic_cast<B*>(pa); 

如果对无继承关系或者没有虚函数的对象指针进行转换、基本类型指针转换以及基类指针转换为派生类指针,都不能通过编译。

 


对于具有标准定义转换的简单类型而言工作的很好。然而,这样的转换符也能不分皂白的应用于类(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 reinterpret_cast

'reinterpret_cast'转换一个指针为其它类型的指针。它也允许从一个指针转换为整数类型。反之亦然。(译注:是指针具体的地址值作为整数值?)
这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。在类型之间指向的内容不做任何类型的检查和转换。

如果情况是从一个指针到整型的拷贝,内容的解释是系统相关的,所以任何的实现都不是方便的。一个转换到足够大的整型能够包含它的指针是能够转换回有效的指针的。

代码:
class A {};
class B {};

A * a = new A;
B * b = reinterpret_cast<B *>(a);
'reinterpret_cast'就像传统的类型转换一样对待所有指针的类型转换。

2 static_cast

'static_cast'允许执行任意的隐式转换和相反转换动作。(即使它是不允许隐式的)

应用到类的指针上,意思是说它允许子类类型的指针转换为父类类型的指针(这是一个有效的隐式转换),同时,也能够执行相反动作:转换父类为它的子类。

在这最后例子里,被转换的父类没有被检查是否与目的类型相一致。
代码:
class Base {};
class Derived : public Base {};

Base *a    = new Base;
Derived *b = static_cast<Derived *>(a);
'static_cast'除了操作类型指针,也能用于执行类型定义的显式的转换,以及基础类型之间的标准转换:

代码:
double d = 3.14159265;
int    i = static_cast<int>(d);

3 dynamic_cast

'dynamic_cast'只用于对象的指针和引用。当用于多态类型时,它允许任意的隐式类型转换以及相反过程。不过,与static_cast不同,在后一种情况里(注:即隐式转换的相反过程),dynamic_cast会检查操作是否有效。也就是说,它会检查转换是否会返回一个被请求的有效的完整对象。
检测在运行时进行。如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL.
代码:
class Base { virtual dummy() {} };
class Derived : public Base {};

Base* b1 = new Derived;
Base* b2 = new Base;

Derived* d1 = dynamic_cast<Derived *>(b1);          // succeeds
Derived* d2 = dynamic_cast<Derived *>(b2);          // fails: returns 'NULL'

如果一个引用类型执行了类型转换并且这个转换是不可能的,一个bad_cast的异常类型被抛出:
代码:
class Base { virtual dummy() {} };
class Derived : public Base { };

Base* b1 = new Derived;
Base* b2 = new Base;

Derived d1 = dynamic_cast<Derived &*>(b1);          // succeeds
Derived d2 = dynamic_cast<Derived &*>(b2);          // fails: exception thrown

4 const_cast

这个转换类型操纵传递对象的const属性,或者是设置或者是移除:
代码:
class C {};

const C *a = new C;

C *b = const_cast<C *>(a);
其它三种操作符是不能修改一个对象的常量性的。
注意:'const_cast'也能改变一个类型的volatile qualifier。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值