C++几个常用类型转换
来源:互联网 发布:linux服务器更换硬盘 编辑:程序博客网 时间:2024/06/05 10:14
static_cast <new_type> (expression) 静态转换
静态转换是最接近于C风格转换,很多时候都需要程序员自身去判断转换是否安全。比如:
double d=3.14159265;
int i = static_cast<int>(d);
但static_cast已经有安全性的考虑了,比如对于不相关类指针之间的转换。参见下面的例子:
1 // class type-casting 2 #include <iostream> 3 using namespace std; 4 5 class CDummy { 6 float i,j; 7 }; 8 9 class CAddition {10 int x,y;11 public:12 CAddition (int a, int b) { x=a; y=b; }13 int result() { return x+y;}14 };15 16 int main () {17 CDummy d;18 CAddition * padd;19 padd = (CAddition*) &d;20 cout << padd->result();21 return 0;22 }
这个例子与之前举的例子很像,只是CAddition与CDummy类没有任何关系了,但main()中C风格的转换仍是允许的padd = (CAddition*) &d,这样的转换没有安全性可言。
如果在main()中使用static_cast,像这样:
1 int main () {2 CDummy d;3 CAddition * padd;4 padd = static_cast<CAddition*> (&d);5 cout << padd->result();6 return 0;7 }
编译器就能看到这种不相关类指针转换的不安全,报出如下图所示的错误:
注意这时不是以warning形式给出的,而直接是不可通过编译的error。从提示信息里可以看到,编译器说如果需要这种强制转换,要使用reinterpret_cast(稍候会说)或者C风格的两种转换。
总结一下:static_cast最接近于C风格转换了,但在无关类的类指针之间转换上,有安全性的提升。
dynamic_cast <new_type> (expression) 动态转换
动态转换确保类指针的转换是合适完整的,它有两个重要的约束条件,其一是要求new_type为指针或引用,其二是下行转换时要求基类是多态的(基类中包含至少一个虚函数)。
看一下下面的例子:
1 #include <iostream> 2 using namespace std; 3 class CBase { }; 4 class CDerived: public CBase { }; 5 6 int main() 7 { 8 CBase b; CBase* pb; 9 CDerived d; CDerived* pd;10 11 pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base12 pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived 13 }
在最后一行代码有问题,编译器给的错误提示如下图所示:
把类的定义改成:
class CBase { virtual void dummy() {} };
class CDerived: public CBase {};
再编译,结果如下图所示:
编译都可以顺利通过了。这里我们在main函数的最后添加两句话:
cout << pb << endl;
cout << pd << endl;
输出pb和pd的指针值,结果如下:
我们看到一个奇怪的现象,将父类经过dynamic_cast转成子类的指针竟然是空指针!这正是dynamic_cast提升安全性的功能,dynamic_cast可以识别出不安全的下行转换,但并不抛出异常,而是将转换的结果设置成null(空指针)。
再举一个例子:
1 #include <iostream> 2 #include <exception> 3 using namespace std; 4 5 class CBase { virtual void dummy() {} }; 6 class CDerived: public CBase { int a; }; 7 8 int main () { 9 try {10 CBase * pba = new CDerived;11 CBase * pbb = new CBase;12 CDerived * pd;13 14 pd = dynamic_cast<CDerived*>(pba);15 if (pd==0) cout << "Null pointer on first type-cast" << endl;16 17 pd = dynamic_cast<CDerived*>(pbb);18 if (pd==0) cout << "Null pointer on second type-cast" << endl;19 20 } catch (exception& e) {cout << "Exception: " << e.what();}21 return 0;22 }
输出结果是:Null pointer on second type-cast
两个dynamic_cast都是下行转换,第一个转换是安全的,因为指向对象的本质是子类,转换的结果使子类指针指向子类,天经地义;第二个转换是不安全的,因为指向对象的本质是父类,“指鹿为马”或指向不存在的空间很可能发生!
最后补充一个特殊情况,当待转换指针是void*或者转换目标指针是void*时,dynamic_cast总是认为是安全的,举个例子:
1 #include <iostream> 2 using namespace std; 3 class A {virtual void f(){}}; 4 class B {virtual void f(){}}; 5 6 int main() { 7 A* pa = new A; 8 B* pb = new B; 9 void* pv = dynamic_cast<void*>(pa);10 cout << pv << endl;11 // pv now points to an object of type A12 13 pv = dynamic_cast<void*>(pb);14 cout << pv << endl;15 // pv now points to an object of type B16 }
运行结果如下:
可见dynamic_cast认为空指针的转换安全的,但这里类A和类B必须是多态的,包含虚函数,若不是,则会编译报错。
reinterpret_cast <new_type> (expression) 重解释转换
这个转换是最“不安全”的,两个没有任何关系的类指针之间转换都可以用这个转换实现,举个例子:
class A {};
class B {};
A * a = new A;
B * b = reinterpret_cast<B*>(a);//correct!
更厉害的是,reinterpret_cast可以把整型数转换成地址(指针),这种转换在系统底层的操作,有极强的平台依赖性,移植性不好。
它同样要求new_type是指针或引用,下面的例子是通不过编译的:
double a=2000.3;
short b;
b = reinterpret_cast<short> (a); //compile error!
const_cast <new_type> (expression) 常量向非常量转换
这个转换好理解,可以将常量转成非常量。
1 // const_cast 2 #include <iostream> 3 using namespace std; 4 5 void print (char * str) 6 { 7 cout << str << endl; 8 } 9 10 int main () {11 const char * c = "sample text";12 char *cc = const_cast<char *> (c) ;13 Print(cc);14 return 0;15 }
从char *cc = const_cast<char *>(c)可以看出了这个转换的作用了,但切记,这个转换并不转换原常量本身,即c还是常量,只是它返回的结果cc是非常量了。
总结
C风格转换是“万能的转换”,但需要程序员把握转换的安全性,编译器无能为力;static_cast最接近于C风格转换,但在无关类指针转换时,编译器会报错,提升了安全性;dynamic_cast要求转换类型必须是指针或引用,且在下行转换时要求基类是多态的,如果发现下行转换不安全,dynamic_cast返回一个null指针,dynamic_cast总是认为void*之间的转换是安全的;reinterpret_cast可以对无关类指针进行转换,甚至可以直接将整型值转成指针,这种转换是底层的,有较强的平台依赖性,可移植性差;const_cast可以将常量转成非常量,但不会破坏原常量的const属性,只是返回一个去掉const的变量。
注:本文中大部分样例来源自C++标准网站:
http://www.cplusplus.com/doc/tutorial/typecasting/
以及微软的MSDN:
http://msdn.microsoft.com/en-us/library/cby9kycs
若有理解出错的地方,望不吝指正。
转自:http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html
- 几个常用的类型转换
- C++几个常用类型转换
- VS2010中String^的几个常用类型转换
- C语言的常用类型转换函数
- C语言常用数值类型转换函数
- <C/C++> 类型转换
- C/C++:类型转换
- 常用类型转换
- 常用的类型转换
- VC常用类型转换
- C++常用类型转换
- 常用类型转换简记
- 常用时间类型转换
- 常用类型的转换
- 类型转换常用方法
- 常用的类型转换
- Erlang常用类型转换
- 常用的类型转换
- sublime packagecontrol 插件的安装
- 使用Java socket 实现 HTTP 协议
- LuaInterface简介
- 提升磁盘IO性能的几个技巧
- [LeetCode] 029. Divide Two Integers (Medium) (C++/Python)
- C++几个常用类型转换
- iOS音频播放 (六):简单的音频播放器实现
- 敏捷开发 Scrum 总结
- ie8 不支持 position:fixed 的简单解决办法
- 如何才能下载资源
- redis缓存机制 保证数据一致性问题
- 804 - Petri Net Simulation
- android 模拟按键
- 虚拟机配置