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种新型类型转换的更多相关文章

  1. C++中四种强制类型转换区别详解

    C++即支持C风格的类型转换,又有自己风格的类型转换.C风格的转换格式很简单,但是有不少缺点的: 1.转换太过随意,可以在任意类型之间转换.你可以把一个指向const对象的指针转换成指向非const对 ...

  2. [转载]C++中四种强制类型转换方式

    C++中四种强制类型转换方式 原文地址:http://www.cnblogs.com/home123/p/6763967.html 类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单( ...

  3. MVVM 一种新型架构框架

    MVVM是Model-View-ViewModel的简写.微软的WPF带来了新的技术体验,如Silverlight.音频.视频.3D.动画……,这导致了软件UI层更加细节化.可定制化.同时,在技术层面 ...

  4. Android TextView里显示两种颜色

    今天介绍一个小技巧,在Android的TextView里设置两种颜色,直接上代码: TextView TV = (TextView)findViewById(R.id.mytextview01); S ...

  5. C#中,三种强制类型转换的对比

    在C#中,我们可以看到三种强制类型转换,比如强制转换成有符号32位整型,可以找到下面三种方式: ① (int)()                ②Convert.ToInt32()          ...

  6. Galera Cluster——一种新型的高一致性MySQL集群架构

    原文链接:https://www.sohu.com/a/147032902_505779,最近被分配定位mysql的问题,学习下. 1. 何谓Galera Cluster 何谓Galera Clust ...

  7. 一种新型远距临场机器人 Fusion / Full Body Surrogacy for Collaborative Communication

    近日,来自日本庆应大学的机器人专家开发出一种新型远距临场机器人 Fusion,允许操作者远程控制别人的身体来帮助他们完成操作任务.Fusion「栖居」在代理者的背上,具备立体视觉和双声道听觉,可以通过 ...

  8. 四种强制类型转换的总结(const_cast、static_cast、dynamic_cast、reinterpreter_cast)

    四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast) 转载 2011年10月03日 23:59:05 标签: stru ...

  9. C++中的关键字用法--- 四种强制类型转换的总结

    四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast 1. C风格的强制类型转换(Type Cast)很简单,不管什么类 ...

随机推荐

  1. [国嵌笔记][023][ARM寻址方式]

    寻找方式 1.处理器根据指令中给出的信息来找到指令所需操作数的方式 2.立即数寻址 操作数本身在指令中给出,立即数前加”#”表示立即数寻址,操作数在指令中 3.寄存器寻址 利用寄存器中的数值作为操作数 ...

  2. memcached内存模型

    内存管理 内存结构 把内存划分成不同的slab class仓库 把仓库切分成不同尺寸的小块(chunk),用来存储缓存数据 数据内存分配 首先根据数据的大小找到对应的slab class 找到空闲的c ...

  3. 通过JiaThis API接口自定义分享功能按钮实现分享功能本地化

    http://www.mdaima.com/jingyan/20.html 最早李雷博客采用的是百度分享插件,为此还发过博文讲解如何在一个页面调用多个按钮分享不同的文章,感兴趣的朋友可以在本站搜索一下 ...

  4. nginx版本如何选择?

    生产环境使用Stable version:最新稳定版,现在最新的版本是nginx-1.8.1 注意各版本的区别:Nginx官网提供了三个类型的版本 1.Mainline version:Mainlin ...

  5. 一天浓缩学习webpack经过

    熟话说浓缩就是精华,哈哈,所以就这么简单粗暴的介绍下吧,写下的都是精华. 已经不是第一次听说webpack,但是我的起步有点晚,现在才看.开门见山~~ 1.什么是webpack? webpack是当下 ...

  6. maven 阿里云仓库配置

    <!-- 设定主仓库,按设定顺序进行查找. --> <repositories> <repository> <id>nexus-aliyun</i ...

  7. python中强大的format函数

    自python2.6开始,新增了一种格式化字符串的函数str.format(),此函数可以快速处理各种字符串.语法 它通过{}和:来代替%. 请看下面的示例,基本上总结了format函数在python ...

  8. FPGA上如何求32个输入的最大值和次大值:分治

    上午在论坛看到个热帖,里头的题目挺有意思的,简单的记录了一下. 0. 题目 在FPGA上实现一个模块,求32个输入中的最大值和次大值,32个输入由一个时钟周期给出.(题目来自论坛,面试题,如果觉得不合 ...

  9. 初次真正意义上的接触Eclipse

    以前就玩安卓app 用过很多软件比如e4a,iapp,aide,lua,但是这都不是真正意义上的安卓编程软件.大二的时候用过Androidstudio,那个软件配置起来太难了,就搁置了. 这次利用机智 ...

  10. elasticsearch java和_head插件对索引文档的增删改查

    利用head插件: 1,创建索引并添加一条数据(yananindex:索引名称,yanantype:索引类型,1:索引id) 2.修改索引数据(索引id1不变,_version是对该索引数据执行了几次 ...