为什么要进行类型转换?
转换的含义是通过改变一个变量的类型为别的类型从而改变该变量的表示方式。为了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符。
Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?
C 风格(C-style)强制转型如下:
(T) expression // 把表达式强制转换成T类型
比如:
int i;
double d;
i = ( int ) d;
比如:
int i;
double d;
i = int (d);
这两种形式之间没有本质上的不同,它纯粹就是一个把括号放在哪的问题。对于具有标准定义转换的简单类型而言这个很好。毕竟是如此好写,然而,这样的转换符也能不分皂白的应用于类(class)和类的指针。貌似有点宽泛的转换,另外C风格的类型转换在程序语句中难以识别。在语法上,类型转换由圆括号和标识符组成,而这些可以用在C++中的任何地方。比如最简单的赋值,这就导致阅读代码的人也可能会忽略这种转换。
为了克服这些缺点,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)
reinterpret_cast 是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(就是说,不可移植)的结果,例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。
'reinterpret_cast'转换一个指针为其它类型的指针。它也允许从一个指针转换为整数类型。反之亦然。这个操作符能够在非相关的类型之间转换。操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。在类型之间指向的内容不做任何类型的检查和转换。'reinterpret_cast'就像传统的类型转换一样对待所有指针的类型转换。
如果情况是从一个指针到整型的拷贝,内容的解释是系统相关的,所以任何的实现都不是方便的。一个转换到足够大的整型能够包含它的指针是能够转换回有效的指针的。
应用实例:
代码:
class A {};
class B {};
A * a = new A;
B * b = reinterpret_cast < B *> (a);
class Base {};
class Derived : public Base {};
Base * a = new Base;
Derived * b = static_cast < Derived *> (a);
double d = 3.14159265 ;
int i = static_cast < int > (d);
class Base { virtual dummy() {} };
class Derived : public Base {};
Base * b1 = new Derived;
Base * b2 = new Base;
Derived * d1 = dynamic_cast < Derived *> (b1); // 成功
Derived * d2 = dynamic_cast < Derived *> (b2); // 失败: 返回 'NULL'
class Base { virtual dummy() {} };
class Derived : public Base { };
Base * b1 = new Derived;
Base * b2 = new Base;
Derived d1 = dynamic_cast < Derived &*> (b1); // 成功
Derived d2 = dynamic_cast < Derived &*> (b2); // 失败:异常抛出
class C {};
const C * a = new C;
C * b = const_cast < C *> (a);
关于volatile限定符:当一个对象的值可能会在编译器的控制或检测之外被改变时,例如一个被系统时钟更新的变量,那么对象应该声明成volatile。编译器执行的某些例行优化行为不能应用在已指定为volatile的对象上。volatile限定符的用法同const非常相似,都是作为类型的附加修饰符。volatile修饰符的主要目的是提示编译器,该对象的值可能在编译器未监测到的情况下被改变。因此编译器不能武断的对引用这些对象的代码作优化处理。