一.static_cast

static_cast 只能用于良性转换,这样的转换风险较低,一般不会发生什么意外,如:

#include <iostream>
#include <cstdlib>
using namespace std; class Complex{
public:
Complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ }
public:
operator double() const { return m_real; } //类型转换函数
private:
double m_real;
double m_imag;
}; int main(){
//下面是正确的用法
int m = ;
Complex c(12.5, 23.8);
long n = static_cast<long>(m); //宽转换,没有信息丢失
char ch = static_cast<char>(m); //窄转换,可能会丢失信息
int *p1 = static_cast<int*>( malloc( * sizeof(int)) ); //将void指针转换为具体类型指针
void *p2 = static_cast<void*>(p1); //将具体类型指针,转换为void指针
double real= static_cast<double>(c); //调用类型转换函数 //下面的用法是错误的
float *p3 = static_cast<float*>(p1); //不能在两个具体类型的指针之间进行转换
p3 = static_cast<float*>(0X2DF9); //不能将整数转换为指针类型 return ;
}

二.const_cast

const_cast用来去掉表达式的 const 修饰或 volatile 修饰。换句话说,const_cast 就是用来将 const/volatile 类型转换为非 const/volatile 类型。如:

#include <iostream>
using namespace std; int main(){
const int n = ;
int *p = const_cast<int*>(&n);
*p = ;
cout<<"n = "<<n<<endl;
cout<<"*p = "<<*p<<endl; return ;
}

运行结果:

n = 100
*p = 234

&n用来获取 n 的地址,它的类型为const int *,必须使用 const_cast 转换为int *类型后才能赋值给 p。由于 p 指向了 n,并且 n 占用的是栈内存,有写入权限,所以可以通过 p 修改 n 的值。

至于为什么通过 n 和 *p 输出的值不一样呢?这是因为 C++ 对常量的处理更像是编译时期的#define,是一个值替换的过程,代码中所有使用 n 的地方在编译期间就被替换成了 100。换句话说,第 8 行代码被修改成了下面的形式:

cout<<"n = "<<<<endl;

这样以来,即使程序在运行期间修改 n 的值,也不会影响 cout 语句了。

三.reinterpret_cast

reinterpret_cast 这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,非常简单粗暴,所以风险很高

#include <iostream>
using namespace std; class A{
public:
A(int a = , int b = ): m_a(a), m_b(b){}
private:
int m_a;
int m_b;
}; int main(){
//将 char* 转换为 float*
char str[]="http://c.biancheng.net";
float *p1 = reinterpret_cast<float*>(str);
cout<<*p1<<endl;
//将 int 转换为 int*
int *p = reinterpret_cast<int*>();
//将 A* 转换为 int*
p = reinterpret_cast<int*>(new A(, ));
cout<<*p<<endl; return ;
}

运行结果:

3.0262e+29

个人感觉这个关键字很危险,所以不推荐使用.

四.dynamic_cast

dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。向上转型是无条件的,不会进行任何检测,所以都能成功;向下转型的前提必须是安全的,要借助 RTTI 进行检测,所有只有一部分能成功。

有以下两点需要注意:

1).newType 和 expression 必须同时是指针类型或者引用类型。换句话说,dynamic_cast 只能转换指针类型和引用类型,其它类型(int、double、数组、类、结构体等)都不行。

2).对于指针,如果转换失败将返回 NULL;对于引用,如果转换失败将抛出std::bad_cast异常。

例:

#include <iostream>
using namespace std; class A{
public:
virtual void func() const { cout<<"Class A"<<endl; }
private:
int m_a;
}; class B: public A{
public:
virtual void func() const { cout<<"Class B"<<endl; }
private:
int m_b;
}; class C: public B{
public:
virtual void func() const { cout<<"Class C"<<endl; }
private:
int m_c;
}; class D: public C{
public:
virtual void func() const { cout<<"Class D"<<endl; }
private:
int m_d;
}; int main(){
A *pa = new A();
B *pb;
C *pc; //情况①
pb = dynamic_cast<B*>(pa); //向下转型失败
if(pb == NULL){
cout<<"Downcasting failed: A* to B*"<<endl;
}else{
cout<<"Downcasting successfully: A* to B*"<<endl;
pb -> func();
}
pc = dynamic_cast<C*>(pa); //向下转型失败
if(pc == NULL){
cout<<"Downcasting failed: A* to C*"<<endl;
}else{
cout<<"Downcasting successfully: A* to C*"<<endl;
pc -> func();
} cout<<"-------------------------"<<endl; //情况②
pa = new D(); //向上转型都是允许的
pb = dynamic_cast<B*>(pa); //向下转型成功
if(pb == NULL){
cout<<"Downcasting failed: A* to B*"<<endl;
}else{
cout<<"Downcasting successfully: A* to B*"<<endl;
pb -> func();
}
pc = dynamic_cast<C*>(pa); //向下转型成功
if(pc == NULL){
cout<<"Downcasting failed: A* to C*"<<endl;
}else{
cout<<"Downcasting successfully: A* to C*"<<endl;
pc -> func();
} return ;
}

运行结果:

Downcasting failed: A* to B*
Downcasting failed: A* to C*
-------------------------
Downcasting successfully: A* to B*
Class D
Downcasting successfully: A* to C*
Class D

C++语言基础(24)-四种类型转换运算符(static_cast、dynamic_cast、const_cast和reinterpret_cast)的更多相关文章

  1. C++中的四种类型转换运算符static_cast、dynamic_cast、const_cast和reinterpret_cast的使用

    1.上一遍讲述了C语言的隐式类型转换和显示类型转换,C语言之所以增加强制类型转换,就是为了强调转换的风险性,但这种强调风险的方式是比较粗放了,粒度比较大,它并没有表明存在什么风险,风险程度如何. 2. ...

  2. 引用、数组引用与指针引用、内联函数inline、四种类型转换运算符

    一.引用 (1).引用是给一个变量起别名 定义引用的一般格式:类型  &引用名 = 变量名: 例如:int a=1;  int  &b=a;// b是a的别名,因此a和b是同一个单元 ...

  3. 从零开始学C++之从C到C++(二):引用、内联函数inline、四种类型转换运算符

    一.引用 (1).引用是给一个变量起别名 定义引用的一般格式:类型  &引用名 = 变量名: 例如:int a=1; int  &b=a;// b是a的别名,因此a和b是同一个单元 注 ...

  4. C++语言中的四种类型转换

    1 引子 这篇笔记是根据StackOverflow上面的一个问题整理而成,主要内容是对C/C++当中四种类型转换操作进行举例说明.在之前其实对它们都是有所了解的,而随着自己在进行总结,并敲了一些测试示 ...

  5. C++中四种类型转换以及const_cast是否能改变常量的问题

    we have four specific casting operators:dynamic_cast, reinterpret_cast, static_cast and const_cast. ...

  6. [转]C++中四种类型转换符的总结

    C++中四种类型转换符的总结 一.reinterpret_cast用法:reinpreter_cast<type-id> (expression)    reinterpret_cast操 ...

  7. C++ 四种类型转换

    在写代码中经常会有很多的隐式类型转换或显式类型转换. 对于隐式的类型转换主要是放生在赋值的时候,讲变量赋值给不同类型的变量的时候就会发生类型转换,如果是宽化转换(即从占字节少的类型向占字节多的类型转换 ...

  8. c++ --> c++中四种类型转换方式

    c++中四种类型转换方式   c风格转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少缺点, 1)它可以在任意类型之间转换,比如你可以把一个指向const对象的指针转换成指向 ...

  9. 【C++】类型转换简述:四种类型转换方式的说明及应用

    本文主要简述在C++中四种类型转换的方式:static_cast.reniterpret_cast.const_cast和dynamic_cast. 在介绍C++类型转换方式之前,我们先来看看C语言的 ...

随机推荐

  1. Linux makefile 教程

    转自:http://blog.csdn.net/liang13664759/article/details/1771246 最近在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指 ...

  2. IntelliJ IDEA maven项目的基础配置

    htt 选择编程风格File->Settings->Apprearance 配置maven路径,同样也是在settings Java Web项目配置 File->Project St ...

  3. kibana-sentinl-监控报警

    kibana 安装 sentin 插件 ./bin/kibana-plugin install https://github.com/sirensolutions/sentinl/releases/d ...

  4. [转]SQL Server 创建数据库邮件

    本文转自:http://www.cnblogs.com/gaizai/p/3358958.html 一. 背景 数据库发邮件通知数据库的运行状态(状态可以通过JOB形式获取)和信息,达到预警的效果. ...

  5. SQL注入深入剖析

    SQL注入是一门很深的学问,也是一门很有技巧性的学问 1.  运算符的优先级介绍 2.  SQL语句执行函数介绍 mysql_query() 仅对 SELECT,SHOW,EXPLAIN 或 DESC ...

  6. mac office 设置默认视图显示比例

    1.打开word 2.fn+option+F11,选中Normal,右键插入模块,复制以下脚本到编辑器中 Sub AutoOpen() ActiveWindow.ActivePane.View.Zoo ...

  7. 转:java中数组与List相互转换的方法

    1.List转换成为数组.(这里的List是实体是ArrayList) 调用ArrayList的toArray方法. toArray public <T> T[] toArray(T[] ...

  8. Python—— 性能分析入门指南

    虽然并非你编写的每个 Python 程序都要求一个严格的性能分析,但是让人放心的是,当问题发生的时候,Python 生态圈有各种各样的工具可以处理这类问题. 分析程序的性能可以归结为回答四个基本问题: ...

  9. Opengl ES 1.x NDK实例开发之六:纹理贴图

    开发框架介绍请參见:Opengl ES NDK实例开发之中的一个:搭建开发框架 本章在第三章(Opengl ES 1.x NDK实例开发之三:多边形的旋转)的基础上演示怎样使用纹理贴图,分别实现了三角 ...

  10. 01-spring安装,hello word

    环境搭建 第一步:安装spring 可以参考这个:http://blog.csdn.net/boredbird32/article/details/50932458 安装成功后,重启后有下面这个Spr ...