C/C++的显式类型转换
2015-01-11 16:02
267 查看
C/C++的显式类型转换
在C/C++中,我们可以显式地将某个值、变量或对象强制转换成某种特定的类型。C
C语言中的显示类型转换非常简单,直接用括号把所需要转换的数据类型括起来放在值的左边即可:int a = 100; long b = (long)a;
但是,还有一种是把值(变量)用括号括起来放在类型前面的做法:
int a = 100; long b = long(a);
C++
在C++中,除了包含以上提到的C语言转换方式,还添加了另外四个显式类型转换的语法,他们分别是:static_cast、dynamic_cast、const_cast和reinterpret_cast。static_cast<type_id>(expression)
static_cast支持典型的窄化转换(信息丢失)、void*强制转换、隐式类型转换和类层次的转换(不安全)。窄化转换:
double d = 0.0; int i ; i = d; //由于double比int的占用字节数要大,所以从double转换到int会有信息丢失,一般这里会编译警告 i = static_cast<int>(d); //使用static_cast编译器不会报警告
void*前置转换:
int i = 5; void* v = &i; //int* t= v; 这一句会导致编译错误,C++不允许直接将void*转化为其他类型指针,需要强制转换 int* j = static_cast<int*>(v);
隐式转换:
int a = 5; double d = a; //double总能容纳一个int,所以会隐式转换 long l = a; //同理,long也是比int大 d = static_cast<double>a; //使用static_cast时为了突出这种转换,跟使用隐式转换没多大区别 l = static_cast<long>a; //同上
类层次的转换,这个跟dynamic_cast的作用一样,可以分别进行上行或下行的类层次的转换,这里把它放到与dynamic_cast一起使用进行对比。
dynamic_cast<type_id>(expression)
dynamic_cast主要是一种类型安全的下行类型转换操作,它的type_id必须是类的指针、引用或者是void*,它与static_cast在类层次的转换有所区别。顾名思义的话,static_cast是静态的类型转换操作,而dynamic就是动态的类型转换,即根据实际对象动态地转换,这里所说的动态主要体现的是所传入的对象类型必须含有虚函数——因为它是靠存储在vtable上的类型信息来判断实际的类型,而dynamic_cast这种动态识别对象信息的能力又称RTTI(run-timetype information),这是面向对象语言的一种机制,这里不再赘述。那么,dynamic_cast有了这种能力之后,与static在类层次上的转换有啥区别呢?
首先,类型层次的转换又分上行与下行,其中上行转换总是安全的(因为一个父类的指针或引用,指向的是一个子类的对象总是安全的),那么下行转换呢?static_cast与dynamic_cast的不同就体现在这里了。看看下面代码:
class B { public: int m_iNum; virtual void foo(); }; class D:public B { public: char* m_szName[100]; }; void func(B* pb) { D* pd1 = static_cast<D*>(pb); D* pd2 = dynamic_cast<D*>(pb); }
如果传给func函数的参数pb实际指向一个D类型的对象,那么无论pd1还是pd2都是正确的转换——指向一个D类型对象;若参数pb指向的是一个B类型的对象,则pd1是一个返回一个指向B对象的D*指针,用这个指针操作将是不安全的(例如访问m_szName[100],而程序员本身可能不知道就会出错),而pd2则是返回一个空指针。所以,一般来说,进行下行的类层次转换都是用dynamic_cast比较安全。不过也有例外,假如类层次中没有定义虚函数(这种设计本身就有问题,因为使用类很大程度就是为了利用其多态的性质),那么就无法使用dynamic_cast了,只能使用static_cast,前提是程序员要知道自己转换的类型是安全的,可以先通过type_id来判别类型(RTTI)再进行静态转换。
const_cast<type_id>(expression)
很容易想象到的是,const_cast是用来进行const相关的转换,可以把一个const对象转换为一个非const对象,同理,反其道而行也是可以的;另外 还可以用来进行volatile的转换。一般来说,非const对象转换为const对象是没问题的,所以其实是不需要使用const_cast。主要是const对象转非const对象,这样就可以修改一个const对象的值了。另外,type_id必须是指针或引用。const int a = 5; int* b = const_cast<int*>(&a); *b = 2;
reinterpret_cast<type_id>(expression)
这是四种显式转换里最不安全、最容易出问题的转换。它是一种低级的位操作,可以把一个对象转换成另一种截然不同的类型,差不多即是重新定义了这个对象。它的type_id同样必须为指针或引用。const int sz = 100; class X { public: int a [sz]; }; int main() { X x; int* x = reinterpret_cast<int*>(&x); for(int*i = x; i < x + sz ; i++) *i = 0; //给x对象的内存清0 //x->a[0] = 1; a指针无法访问x对象的成员,这样做会使编译器报错 return 0; }reinterpret_cast的思想在于当需要的时候,所得到的东西(上面的例子是x指针)已经不同了,以至于它无法进行原来对象(x对象)的操作。
总结:使用C++的显式类型转换语法比C原有的强制类型转换更好更安全,同时当使用C++的显示类型转换在出错的时候更加容易发现并定位错误。
相关文章推荐
- C++ 显式类型转换
- C++ 中的cast(显式类型转换)
- C++的显式类型转换
- 转:C++ 中的 cast(显式类型转换)
- C++ 中的 cast(显式类型转换)
- c++ 显式类型转换
- C++中的显式类型转换
- C++ 中的 cast(显式类型转换
- C++类型转换分为:隐式类型转换和显式类型转换
- C++ 中的 cast(显式类型转换)
- C++的显式类型转换
- C++ 中的 cast(显式类型转换)
- C++类型转换分为:隐式类型转换和显式类型转换
- C++中的显式类型转换
- 经典问题3:c/c++ 程序设计 ---类型转换问题
- C++ CLR 文件读取 类型转换
- C++中的显式构造函数
- C++中显式和隐式初始化和类型转换
- C++中构造函数和析构函数显式调用的方法
- C++ 隐式和显式 初始化,类型转换