C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast
1. c强制转换与c++强制转换
c语言强制类型转换主要用于基础的数据类型间的转换,语法为:
(type-id)expression//转换格式1 type-id(expression)//转换格式2
c++除了能使用c语言的强制类型转换外,还新增了四种强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast,主要运用于继承关系类间的强制转化,语法为:
static_cast<new_type> (expression)
dynamic_cast<new_type> (expression)
const_cast<new_type> (expression)
reinterpret_cast<new_type> (expression)
备注:new_type为目标数据类型,expression为原始数据类型变量或者表达式。
《Effective C++》中将c语言强制类型转换称为旧式转型,c++强制类型转换称为新式转型。
2. static_cast、dynamic_cast、const_cast、reinterpret_cast
static_cast
char a = 'a';
int b = static_cast<char>(a);//正确,将char型数据转换成int型数据 double *c = new double;
void *d = static_cast<void*>(c);//正确,将double指针转换成void指针 int e = ;
const int f = static_cast<const int>(e);//正确,将int型数据转换成const int型数据 const int g = ;
int *h = static_cast<int*>(&g);//编译错误,static_cast不能转换掉g的const属性
if(Derived *dp = static_cast<Derived *>(bp)){//下行转换是不安全的
//使用dp指向的Derived对象
}
else{
//使用bp指向的Base对象
}
if(Base*bp = static_cast<Derived *>(dp)){//上行转换是安全的
//使用bp指向的Derived对象
}
else{
//使用dp指向的Base对象
}
dynamic_cast
dynamic_cast<type*>(e)
dynamic_cast<type&>(e)
dynamic_cast<type&&>(e)
type必须是一个类类型,在第一种形式中,type必须是一个有效的指针,在第二种形式中,type必须是一个左值,在第三种形式中,type必须是一个右值。在上面所有形式中,e的类型必须符合以下三个条件中的任何一个:e的类型是是目标类型type的公有派生类、e的类型是目标type的共有基类或者e的类型就是目标type的的类型。如果一条dynamic_cast语句的转换目标是指针类型并且失败了,则结果为0。如果转换目标是引用类型并且失败了,则dynamic_cast运算符将抛出一个std::bad_cast异常(该异常定义在typeinfo标准库头文件中)。e也可以是一个空指针,结果是所需类型的空指针。
if(Derived *dp = dynamic_cast<Derived *>(bp)){
//使用dp指向的Derived对象
}
else{
//使用bp指向的Base对象
}
值得注意的是,在上述代码中,if语句中定义了dp,这样做的好处是可以在一个操作中同时完成类型转换和条件检查两项任务。
(2)引用类型
因为不存在所谓空引用,所以引用类型的dynamic_cast转换与指针类型不同,在引用转换失败时,会抛出std::bad_cast异常,该异常定义在头文件typeinfo中。
void f(const Base &b){
try{
const Derived &d = dynamic_cast<const Base &>(b);
//使用b引用的Derived对象
}
catch(std::bad_cast){
//处理类型转换失败的情况
}
}
const_cast
const_cast,用于修改类型的const或volatile属性。
const int g = ;
int *h = const_cast<int*>(&g);//去掉const常量const属性 const int g = ;
int &h = const_cast<int &>(g);//去掉const引用const属性 const char *g = "hello";
char *h = const_cast<char *>(g);//去掉const指针const属性
reinterpret_cast
new_type必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。
reinterpret_cast意图执行低级转型,实际动作(及结果)可能取决于编辑器,这也就表示它不可移植。
举一个错误使用reintepret_cast例子,将整数类型转换成函数指针后,vc++在执行过程中会报"...中的 0xxxxxxxxx 处有未经处理的异常: 0xC0000005: Access violation"错误:
#include <iostream>
using namespace std;
int output(int p){
cout << p <<endl;
return 0;
} typedef int (*test_func)(int );//定义函数指针test_func
int main(){
int p = ;
test_func fun1 = output;
fun1(p);//正确
test_func fun2 = reinterpret_cast<test_func>(&p);
fun2(p);//...处有未经处理的异常: 0xC0000005: Access violation
return ;
}
IBM的C++指南、C++之父Bjarne Stroustrup的FAQ网页和MSDN的Visual C++也都指出:错误的使用reinterpret_cast很容易导致程序的不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。
// expre_reinterpret_cast_Operator.cpp
// compile with: /EHsc
#include <iostream> // Returns a hash code based on an address
unsigned short Hash( void *p ) {
unsigned int val = reinterpret_cast<unsigned int>( p );
return ( unsigned short )( val ^ (val >> ));
} using namespace std;
int main() {
int a[];
for ( int i = ; i < ; i++ )
cout << Hash( a + i ) << endl;
}
class A {
public:
int m_a;
};
class B {
public:
int m_b;
};
class C : public A, public B {};
C c;
printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));
3. c++强制转换注意事项
- 新式转换较旧式转换更受欢迎。原因有二,一是新式转型较易辨别,能简化“找出类型系统在哪个地方被破坏”的过程;二是各转型动作的目标愈窄化,编译器愈能诊断出错误的运用。
- 尽量少使用转型操作,尤其是dynamic_cast,耗时较高,会导致性能的下降,尽量使用其他方法替代。
参考资料:
a):http://en.cppreference.com/w/cpp/language/static_cast
b):http://en.cppreference.com/w/cpp/language/dynamic_cast
c):http://en.cppreference.com/w/cpp/language/const_cast
d):http://en.cppreference.com/w/cpp/language/reinterpret_cast
e):《Effective C++》条款27:尽量少做转型动作
f): 百度百科
g) 《C++ Primer》
C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast的更多相关文章
- static_cast dynamic_cast const_cast reinterpret_cast总结对比
[本文链接] http://www.cnblogs.com/hellogiser/p/static_cast-dynamic_cast-const_cast-reinterpret_cast.html ...
- c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast
c++强制类型转换:dynamic_cast.const_cast .static_cast.reinterpret_cast 博客分类: C/C++ CC++C#编程数据结构 dynamic_ca ...
- 四种强制类型转换的总结(const_cast、static_cast、dynamic_cast、reinterpreter_cast)
四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast) 转载 2011年10月03日 23:59:05 标签: stru ...
- C++雾中风景11:厘清C++类型转换(static_cast,dynamic_cast,reinterpret_cast,const_cast)
C++是一门弱类型的语言,提供了许多复杂和灵巧类型转换的方式.笔者之前写的Python与Go都是强类型的语言,对这种弱类型的设计实在是接受无力啊~~ ( 生活所迫,工作还得写C++啊~~)C++语言提 ...
- 【C++】 四种强制类型转换(static_cast 与 dynamic_cast 的区别!)
强制类型转换 1. static_cast 2. dynamic_cast 3. const_cast 4. reinterpret_cast 5. 为什么要需要四种类型转换? 1. static_c ...
- static_cast, dynamic_cast, const_cast
http://www.cnblogs.com/chio/archive/2007/07/18/822389.html 首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1 ...
- static_cast, dynamic_cast, const_cast探讨
转自:http://www.cnblogs.com/chio/archive/2007/07/18/822389.html 首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 ...
- 【C++专题】static_cast, dynamic_cast, const_cast探讨
首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion ...
- C++之static_cast, dynamic_cast, const_cast
转自:http://www.cnblogs.com/chio/archive/2007/07/18/822389.html 首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 ...
- C++强制类型转换操作符 dynamic_cast
dynamic_cast是四个强制类型转换操作符中最特殊的一个,它支持运行时识别指针或引用. >>>>>>>>>>>编译器的RTTI设 ...
随机推荐
- Spring+SpringMVC+MyBatis深入学习及搭建(五)——动态sql
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6908763.html 前面有讲到Spring+SpringMVC+MyBatis深入学习及搭建(四)——My ...
- js实现导航菜单栏随着屏幕的滚动进行滚动的效果
$(window).scroll(function () { var $nav = $(".floatingMenu ul li"), length = $nav.length-1 ...
- 在附件管理模块中增加对FTP 上传和预览的支持
在之前介绍的附件管理模块里面<Winform开发框架之通用附件管理模块>以及<Winform开发框架之附件管理应用>,介绍了附件的管理功能,通过对数据库记录的处理和文件的管理, ...
- ActionContext、ServletContext、pageContext的区别?
ActionContext是当前的Action的上下文环境,通过ActionContext可以获取到request.session.ServletContext等与Action有关的对象的引用: Se ...
- node.js零基础详细教程(3):npm包管理、git github的使用
第三章 建议学习时间4小时 课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑 ...
- Navicat连接报错:cannot load OCI DLL,126
32位系统下报错:cannot load OCI DLL,126 解决方法:navicat 菜单中 -工具->选项->OCI 选择oracle安装目录下bin里面的oci.dll 在win ...
- 深入理解 JavaScript 事件循环(二)— task and microtask
引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...
- git常用命令,助你快速入门
git是程序员中最常用的版本控制工具,学会git的基本使用是十分重要,特别是在公司里面的协同开发,废话不多说,下面贴出常用的命令. 1.基本配置 # 既然git是多人协同的工具,别人要看到你提交代码的 ...
- MySQL,Oracle,PostgreSQL 数据库web维护客户端管理工具
TreeDMS数据库管理系统使用JAVA开发,采用稳定通用的springMVC +JDBC架构,实现基于WEB方式对 MySQL,Oracle,PostgreSQL 等数据库进行维护管理操作. 功能包 ...
- docker私有库搭建过程(Registry)
实验环境: CentOS7 1611 Docker 1.12.6 registry 2.0 1.安装并运行registry 安装: [root@docker01 ~]# docker pull r ...