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. PHPStorm+PHPStudy配置XDebug

    img { max-width: 100% } 上一节里面从PHPStudy+PHPStorm的配置,到最后发布,PHPStorm只是承担了编辑器和发布站点的任务,但是还没有办法像Visual Stu ...

  2. [国嵌笔记][008-009][远程登录Linux]

    [国嵌笔记][008][远程登录Linux] 1.windows与Linux能够相互ping通 2.关闭Linux防火墙 /etc/init.d/iptables stop 3.通过ssh(字符界面) ...

  3. [国嵌笔记][005][Linux命令详解]

    用户管理类命令 添加用户:useradd name 删除用户:userdel -r name "-r"表示删除对应用户的目录 修改密码:passwd name 切换用户:su - ...

  4. java.lang.NoSuchMethodError: javax.wsdl.xml.WSDLReader.readWSDL(Ljavax/wsdl/xml/WSDLLocator;Lorg/w3c/dom/Element;)Ljavax/wsdl/Definition;

    http://stackoverflow.com/questions/6066054/whats-wrong-with-my-apache-cxf-client You likely have a 1 ...

  5. 如何在外部终止一个pengding的promise对象

    今天在整理前段时间做过的项目,发现之前在集成web环信的时候遇到过一个奇怪的需求:需要终止一个正在进行等待返回的promise,或者阻止其调用resolve和reject.(具体为何会有这种需求我也不 ...

  6. PHP结合Ueditor并修改图片上传路径

    投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2016-10-16 我要评论 使用ueditor编辑器,附件默认在ueditor/php/upload/, 但是大家的附件地址的默认路 ...

  7. 7系列高速收发器总结 GTP IP核使用篇

    上一篇7系列收发器博文讲解了GTP IP核的基本配置,本文继续分析如何将它使用起来.生成IP核后打开example design,先看看工程中包含的文件结构. 顶层文件下包含了gtp ip核系统顶层文 ...

  8. vue学习笔记(五)——指令

    13条指令 1. v-text (数据绑定语法-插值) <span v-text="msg"></span> <!-- 和下面的一样 --> & ...

  9. Java泛型类和泛型方法

    java编程思想说道: 泛型类是应用在整个类上,但同时可以在类中包含参数化方法,而这个方法所在的类可以是泛型,也可以不是泛型,也就是说是否有泛型方法,与其所在的类是否是泛型类没有关系. 泛型方法是的该 ...

  10. JS中获取session中传过来的值对象

    摘录自:http://www.360doc.com/content/11/0316/13/5790498_101627263.shtml 把某一对象置于session范围内,并在JSP页面中提取ses ...