5.C++里的4种新型类型转换

时间:2022-12-26 00:15:20

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);
}

输出结果如下图所示:

5.C++里的4种新型类型转换

从上图可以看到,只有当运行代码时,才会出现段错误问题.

当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&plus;&plus;中四种强制类型转换区别详解

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

  2. &lbrack;转载&rsqb;C&plus;&plus;中四种强制类型转换方式

    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&num;中,三种强制类型转换的对比

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

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

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

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

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

  8. 四种强制类型转换的总结&lpar;const&lowbar;cast、static&lowbar;cast、dynamic&lowbar;cast、reinterpreter&lowbar;cast&rpar;

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

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

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

随机推荐

  1. html基本的内容

    1.表现各标签的特征 <img>中的src(source)即为属性 属性都是以"属性名 = 值"的形式出现 属性的值建议用引号括起来 属性建议均以键值对的形式括起来 一 ...

  2. 扩展KMP --- HDU 3613 Best Reward

    Best Reward Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3613 Mean: 给你一个字符串,每个字符都有一个权 ...

  3. 初次体验架设PHP网站

     最近需要快速架设一个网站,因此淘了一份成型的模板,然后就开始..过程比较曲折. 测试环境:Win7旗舰+IIS7.5+mysql5.6+PHP5.2.17+PHPManagerForIIS-1.1. ...

  4. scp&comma;ssh双机互信操作步骤

     Node1:# ssh-keygen -t rsa 这一步是生成密钥# ssh-copy-id -i ~/.ssh/id_rsa.pub root@node2.xueping365.com ~/.s ...

  5. Navicat 导入数据报错 --- 1153 - Got a packet bigger than &&num;39&semi;max&lowbar;allowed&lowbar;packet&&num;39&semi; bytes

    在用Navicat导入SQL文件时报错:MySql 错误 Err [Imp] 1153 - Got a packet bigger than 'max_allowed_packet' bytes 查了 ...

  6. &lbrack;Ramda&rsqb; Compose and Curry

    Curry: The idea of Curry is to spreate the data from the function. Using Curry to define the functio ...

  7. MyXLS案例

    using System; using System.Data; using org.in2bits.MyXls; namespace Maticsoft.Common { /// <summa ...

  8. kali linux 网络渗透测试学习笔记(二)OWASP ZAP工具扫描SQL injection漏洞失败

    按照惯例,利用OWASP ZAP工具扫描SQL injection漏洞时,应该很快就可以扫描出来,但是在笔者进行扫描的时候,却遇到了以下状况: 这说明了该工具根本就没能够扫描出SQL注入的漏洞,不知道 ...

  9. linux之xxx 不在 sudoers 文件中,此事将被报告&lpar;转载)

    linux中创建用户命令为:useradd 用户名, eg: useradd test 指定密码:passwd test 但是有时候我们需要使用test运行执行一些root用户才有权限执行的命令,此时 ...

  10. C&num;异步编程基础入门总结

    1.前言 *.NET Framework提供了执行异步操作的三种模式: 异步编程模型(APM)模式(也称为IAsyncResult的模式),其中异步操作要求Begin和End方法(例如,BeginWr ...