一直以来,Coding时沿袭了在C语言中编程的习惯,在对不同类型数据作转换时,也按照C语言的处理方法,如下:
在C语言中,在进行自动类型转换的时候,如果原来的数是无符号数,那么在扩展的时候,高位填充的是0;如果是有符号数,那么高位填充的时符号位!这一点有点类似于“>>”操作符,当无符号数右移的时候,高位填充的是0;有符号数右移的时候,高位填充的是符号位。
C语言的类型转换分为:自动类型转换(编译器完成,隐式)和强制类型转换(自己显示去做的)。
(1)自动类型转换
赋值(=右边转成=左边的);混合运算(原则:就高不就低);函数返回值的类型转换 int fun { double d=1.21; return d; }
高 double ←← float
↑ ↑
↑ long
↑ ↑
↑ unsigned
↑ ↑
低 int ←← char,short
自动转换顺序表
(2)强制类型转换
强制将参与运算的变量或常量转换成希望出现的值。
eg: (double)(3+2), (int)(a+b) , ( int)(3.1415926) ;
今天了解到,在C++中,除了使用C语言的类型转换方式,它还提供了用于强制类型的显示转换的四种方法,相较于C语言,它可以提供更好的强制转换过程,使程序员的意图更为明确。
与C语言 TYPEA var1=(TYPEB) var2;的形式不同,C++提供的强制类型转换的格式为:
TYPEA var1=强制转换类型符<TYPEB> var2;
强制转换类型符有:reinterpret_cast,static_cast,dynamic_cast和const_cast四种。以下将对其进行具体的说明和举例,并对四者进行区分:
(1)重新解释类型转换 reinterpret_cast:
语法: returnvalue=reinterpret_cast<casting_value>;
它修改了操作数类型,但仅仅是重新解释了对象的比特模型而没有进行二进制转换。
从语法上看,这个操作符仅用于指针类型的转换(返回值是指针)。它用来将一个类型指针转换为另一个类型指针,它只需在编译时重新解释指针的类型。这个操作符基本不考虑转换类型之间是否是相关的。因此往往不安全,应尽量少使用。关于reinterpret_cast的本质,http://blog.csdn.net/u013700658/article/details/25993815 一文做的试验很好的解释了reinterpret_cast不做二进制转换的特点。
(2)静态类型转换 static_cast:
语法:returnvalue=static_cast<casting_value>;
它类似于C风格的强制转换。无条件转换,静态类型转换。运行时不进行安全检查。主要用于:
【1】 基类和子类之间转换:其中子类指针转换成父类指针是安全的;但父类指针转换成子类指针是不安全的。(基类和子类之间的动态类型转换建议用dynamic_cast)
【2】 基本数据类型转换。enum, struct, int, char, float等。static_cast不能进行无关类型(如非基类和子类)指针之间的转换。
【3】 把空指针转换成目标类型的空指针。
【4】 把任何类型的表达式转换成void类型。
【5】static_cast不能去掉类型的const、volitale属性(用const_cast)。
1 int n =6; 2 double d = static_cast<double>(n); // 基本类型转换 3 int *pn =&n; 4 double *d = static_cast<double*>(&n) //无关类型指针转换,编译错误 5 void *p = static_cast<void*>(pn); //任意类型转换成void类型
(3)动态类型转换 dynamic_cast:
有条件转换,动态类型转换,运行时类型安全检查(转换失败返回NULL):
【1】 安全的基类和子类之间转换。
【2】 必须要有虚函数。
【3】 相同基类不同子类之间的交叉转换。但结果是NULL。
class BaseClass
{
public:
int m_iNum;
virtualvoid foo(){}; //基类必须有虚函数。保持多态性才能使用dynamic_cast
};
class DerivedClass: public BaseClass
{
public:
char*m_szName[100];
void bar(){};
};
BaseClass* pb =new DerivedClass();
DerivedClass *pd1 = static_cast<DerivedClass *>(pb); //子类->父类,静态类型转换,正确但不推荐
DerivedClass *pd2 = dynamic_cast<DerivedClass *>(pb); //子类->父类,动态类型转换,正确
BaseClass* pb2 =new BaseClass();
DerivedClass *pd21 = static_cast<DerivedClass *>(pb2); //父类->子类,静态类型转换,危险!访问子类m_szName成员越界
DerivedClass *pd22 = dynamic_cast<DerivedClass *>(pb2); //父类->子类,动态类型转换,安全的。结果是NULL
(4)去const类型转换 const_cast:
例子:
class TryStatic
{
public:
int ts;
};
const TryStatic test;
//test.ts = 100; //程序中直接修改了const类型,将导致编译错误
TryStatic &test2 = const_cast<test&>(ts);
test2.ts =100;