5.C++里的4种新型类型转换
1首先来回顾C的强制转换
大家都知道,在编译C语言中的强制转换时,编译器不会检查转换是否成功,都会编译正确.
比如:
#include "stdio.h" struct Position
{
int x;
int y;
}; int main()
{
int i;
struct Position *p; i=0x123456; p=(struct Position *)i; printf("px=%d,py=%d\n",p->x,p->y);
}
输出结果如下图所示:

从上图可以看到,只有当运行代码时,才会出现段错误问题.
当C代码上千行时,若出现这种问题,是非常难找的.
2.C++的新型类型转换
所以在C++中,便引入了4种强制类型转换
2.1 static_cast(静态类型转换)
- 用于基本数据类型以及对象之间的转换(char,int,const int等)
- 不能用于基本数据类型指针之间的转换(char *,int *等)
- 用于有继承关系类对象指针之间的转换
- 用于类指针之间的转换
示例-基本数据:
int i = 0x45;
char c = 'c';
c = static_cast<char>(i);
//char* pc = static_cast<char*>(&i); //此行错误,不能用于基本指针之间转换
示例-基本数据与对象转换:
class Test{
public:
explicit Test(int i) //只能显示调用
{
cout<<i<<endl;
}
};
int main()
{
Test t = static_cast<Test>(3.55); //等价于 : Test t(3);
}
示例-有继承关系的类对象指针转换:
class Parent
{
public:
int mm;
Parent(int i)
{
mm=i;
cout<<"Parent:"<<i<<endl;
} }; class Child : public Parent
{
public:
int mval;
Child(int i):Parent(i)
{
mval=i;
cout<<"Child:"<<i<<endl;
}
}; int main()
{
Parent *p =new Parent(); //会调用父类构造函数
Child *c = static_cast <Child *> (p) ; //并不会调用子类构造函数,此时的mval成员为随机值
c->mval=;
cout<<"mval:"<<c->mval<<endl;
cout<<"mm:"<<c->mm<<endl; //此时的c->mm指向的对象就是p->mm
c->mm=100; //修改c->mm 等价于修改p->mm
cout<<"mm:"<<p->mm<<endl;
}
运行打印:
Parent:
mval:100
mm:3
mm:100
2.2 const_cast(去常类型转换)
- 常用于去除const类对象的只读属性
- 且强制转换的类型必须是指针*或引用&
示例1:
const int x =; //const:定义一个常量x const int& j =; //const引用:定义一个只读变量j int& p1= const_cast<int&>(x); //强制转换int & int *p2 = const_cast<int*>(&j); //强制转换int* //int p3 = const_cast<int>(j); //此行错误,不能转换普通数据型 p1=;
*p2=; printf("x=%d, j=%d\n",x,j);
printf("p1=%d *p2=%d\n",p1,*p2);
输出结果:
x= j= p1= *p2=
从输出结果,可以看出修改p1,p2,只有j内容变换了,是因为变量j用const引用定义的,所以是个只读变量.
示例2-去除const类对象的只读属性
class Test
{
public:
int mval;
Test():mval()
{ }
}; int main()
{
const Test n1; //n1.mval = 100; //error,不能直接修改常量对象的成员 Test *n2 = const_cast<Test *>(&n1); //通过指针*转换
Test &n3 = const_cast<Test &>(n1); //通过引用&转换 n2->mval = ; cout<<n1.mval<<endl; //打印20 n3.mval = ; cout<<n1.mval<<endl; //打印30
}
2.3 dynamic_cast(动态类型转换)
- 用于有继承关系的类指针(引用)间的转换
- 用于有交叉关系的类指针(引用)间的转换
- 具有类型检查的功能,编译时会去检查使用的方法是否正确,转换是否成功只有在程序运行时才能知道
- 类中必须有虚函数的支持
- 不能用于基本数据类型指针之间的转换(char *,int *等)
-当转换为指针时:
- 转换成功 : 得到目标类型的指针
- 转换失败 : 得到一个空指针
-当转换为引用时:
- 转换成功 : 得到目标类型的引用
- 转换失败 : 得到一个异常操作信息
示例-通过子类指针去指向父类:
#include <iostream> using namespace std; class Base
{
public:
Base()
{
cout << "Base::Base()" << endl;
} virtual ~Base()
{
cout << "Base::~Base()" << endl;
}
}; class Derived : public Base
{
}; int main()
{
Base* p = new Base; //初始化父类指针 Derived* pd = dynamic_cast<Derived*>(p); //由于父类指针指向的是父类,没有子类虚函数表,所以转换失败
cout << "pd = " << pd << endl; //转换失败,打印 0 delete p; p = new Derived;
pd = dynamic_cast<Derived*>(p); //由于父类指针指向的是子类,所以有子类虚函数表
cout <<"pd = " << pd <<endl; //转换成功,打印地址值 delete p; return ;
}
示例-通过多重继承下的类指针转换:
class BaseA
{
public:
virtual void funcA()
{
cout<<"BaseA: funcA()"<<endl;
} };
class BaseB
{
public:
virtual void funcB()
{
cout<<"BaseB: funcB()"<<endl;
} };
class Derived : public BaseA,public BaseB
{
};
int main()
{
Derived d;
BaseA *pa=&d; pa->funcA(); //打印 BaseA: funcA() /*通过强制转换执行*/
BaseB *pb=(BaseB *)pa;
pb->funcB(); //还是打印 BaseA: funcA(), 因为pb还是指向pa,执行的还是pa的虚函数表 /*通过dynamic_cast执行*/
pb = dynamic_cast<BaseB *>(pa);
pb->funcB(); //打印 BaseB: funcB()
//编译器会去检测pa所在的地址,发现有多个虚函数表,然后根据 <BaseB *>来修正指针pb
return ; }
2.4 reinterpret_ cast(解读类型转换)
- 用于所有指针的强制转换
(解读是指:对要转换的数据进行重新的解读)
例如:
int i = ;
char j='c';
int *p1=reinterpret_cast<int *>(&i);
char *p2=reinterpret_cast<char *>(&j);
//int p3=reinterpret_cast<int >i; //此行错误,不能转换普通数据型
5.C++里的4种新型类型转换的更多相关文章
- C++中四种强制类型转换区别详解
C++即支持C风格的类型转换,又有自己风格的类型转换.C风格的转换格式很简单,但是有不少缺点的: 1.转换太过随意,可以在任意类型之间转换.你可以把一个指向const对象的指针转换成指向非const对 ...
- [转载]C++中四种强制类型转换方式
C++中四种强制类型转换方式 原文地址:http://www.cnblogs.com/home123/p/6763967.html 类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单( ...
- MVVM 一种新型架构框架
MVVM是Model-View-ViewModel的简写.微软的WPF带来了新的技术体验,如Silverlight.音频.视频.3D.动画……,这导致了软件UI层更加细节化.可定制化.同时,在技术层面 ...
- Android TextView里显示两种颜色
今天介绍一个小技巧,在Android的TextView里设置两种颜色,直接上代码: TextView TV = (TextView)findViewById(R.id.mytextview01); S ...
- C#中,三种强制类型转换的对比
在C#中,我们可以看到三种强制类型转换,比如强制转换成有符号32位整型,可以找到下面三种方式: ① (int)() ②Convert.ToInt32() ...
- Galera Cluster——一种新型的高一致性MySQL集群架构
原文链接:https://www.sohu.com/a/147032902_505779,最近被分配定位mysql的问题,学习下. 1. 何谓Galera Cluster 何谓Galera Clust ...
- 一种新型远距临场机器人 Fusion / Full Body Surrogacy for Collaborative Communication
近日,来自日本庆应大学的机器人专家开发出一种新型远距临场机器人 Fusion,允许操作者远程控制别人的身体来帮助他们完成操作任务.Fusion「栖居」在代理者的背上,具备立体视觉和双声道听觉,可以通过 ...
- 四种强制类型转换的总结(const_cast、static_cast、dynamic_cast、reinterpreter_cast)
四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast) 转载 2011年10月03日 23:59:05 标签: stru ...
- C++中的关键字用法--- 四种强制类型转换的总结
四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast 1. C风格的强制类型转换(Type Cast)很简单,不管什么类 ...
随机推荐
- Vue2反向代理
前一段时间写了一个vue2的小项目,用的是vue-cli脚手架搭建的项目,项目里需要跨域,但又不能使用jsonp,上网查了一下,发现有一个之前没接触过的词语--反向代理. 什么是"反向代 ...
- Linux命令之远程下载命令:wget
转自:http://www.cnblogs.com/peida/archive/2013/03/18/2965369.html Linux系统中的wget是一个下载文件的工具,它用在命令行下.对于Li ...
- nginx 防火墙、权限问题
1.nginx安装,配置完成之后,尝试访问没有响应,主机可以ping通,/var/log/nginx/access.log日志没有查到任何记录 解决方法:查看linux防火墙,关闭 命令:ipta ...
- 将自己的代码托管到github上
这几天一直在做一个爬虫的小demo,代码基本写的差不多了,想着如何把他放在一个地方,如是乎注册了一个github账号,开始了自己的git之旅. 首先是下载git,这个我就不多说啦!到处都有推荐看看廖雪 ...
- 【开发技术】json
json(JavaScript Object Notation) JavaScript对象符号是一种结构化轻量级的数据传输格式,很多场合替代XML文件格式 JSON格式化校验:http://www.b ...
- Android-第二天
1.Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器 ...
- Hadoop集群的JobHistoryServer详解(转载)
Hadoop自带了一个历史服务器,可以通过历史服务器查看已经运行完的Mapreduce作业记录,比如用了多少个Map.用了多少个Reduce.作业提交时间.作业启动时间.作业完成时间等信息.默认情况下 ...
- Jquery实现两级联动
最后结果如下: 关键代码如下: <select name="customerCondition['credibilityBegin']" id="credibili ...
- CCF系列之相邻数对(201409-1)
试题编号: 201409-1 时间限制: 1.0s 内存限制: 256.0MB 问题描述 给定n个不同的整数,问这些数中有多少对整数,它们的值正好相差1. 输入格式 输入的第一行包含一个整数n,表示给 ...
- arcgis地图服务之 identify 服务
arcgis地图服务之 identify 服务 在近期的一次开发过程中,利用IdentityTask工具查询图层的时候,请求的参数中ImageDisplay的参数出现了错误,导致查询直接不能执行,百度 ...