C++基础知识 - C++的类型转换

2023-11-10

类型转换使用建议

  • static_cast静态类型转换,编译的时c++编译器会做编译时的类型检查;隐式转换;
    基本类型转换,父子类之间合理转换

  • 若不同类型之间,进行强制类型转换,用reinterpret_cast<>() 进行重新解释

  • 建 议:
    C语言中 能隐式类型转换的,在c++中可用 static_cast<>()进行类型转换。因C++编译器在编译检查一般都能通过;C语言中不能隐式类型转换的,在c++中可以用 reinterpret_cast<>() 进行强制类型解释。

  • 总结:static_cast<>()和reinterpret_cast<>() 基本上把C语言中的 强制类型转换给覆盖,注意reinterpret_cast<>()很难保证移植性。

  • dynamic_cast<>(),动态类型转换,安全的虚基类和子类之间转换;运行时类型检查

  • const_cast<>(),去除变量的只读属性

最后的忠告:程序员必须清楚的知道: 要转的变量,类型转换前是什么类型,类型转换 后是什么类型,转换后有什么后果。
C++大牛建议:一般情况下,不建议进行类型转换;避免进行类型转换。

C++的类型转换

  • 旧式转型 C风格的强制类型:

    		TYPE b = (TYPE) a     
    		例如:  
    		int i = 48;
    		char c = (char) i;	//强制转换
    
  • 新式转型C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用。
    格式:

     TYPE b = 类型操作符<TYPE> ( a )   
     类型操作符= static_cast | reinterpreter_cast | dynamic_cast | const_cast 
    

static_cast

静态类型转换(斯文的劝导,温柔的转换)。如int转换成char

主要用法:

  • 用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。上行指针或引用(派生类到基类)转换安全,下行不安全
  • 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
  • 把空指针转换成目标类型的空指针。
  • 把任何类型的表达式转换成void类型。
#include <iostream>
#include <Windows.h>
using namespace std;

class Animal {public: virtual void cry() = 0;};
class Dog : public Animal {public: void cry() {cout << "汪汪汪" << endl;}};
class Cat : public Animal {public: void cry() {cout << "喵喵喵" << endl;}};

int main(void){
	//方式一, 父类与子类之间的转换
	Dog *d1 = new Dog();
	Animal* a1 = static_cast<Animal*>(d1);	//子类指针转型为父类
	d1 = static_cast<Dog*>(a1);				//父类指针转换为子类指针		

	Cat* c1 = static_cast<Cat*>(a1);//不安全, 因为此时父类指向了Dog类	
	c1->cry();	//输出的是Dog类的 "汪汪汪"

	Dog d2;
	Animal& a2 = static_cast<Animal&>(d2);	//子类引用转型到父类

	//方式二, 普通类型转换
	int k = 97;
	char c = static_cast<char>(k);
	cout << c << endl;

	//方式三, 空指针转换为目标类型的空指针
	int* p1 = static_cast<int*>(NULL);
	char* cp = static_cast<char*>(NULL);

	//方式四, 把任何类型的表达式,转换为void类型
	int* p = new int[10];
	void* vp = static_cast<void*>(p);

	system("pause");
	return 0;
}

reinterpret_cast

  • 重新解释类型(挂羊头,卖狗肉) 不同类型间的互转,数值与指针间的互转

  • 用法: TYPE b = reinterpret_cast ( a )
    TYPE必须是一个指针、引用、算术类型、函数指针.

  • 忠告:滥用 reinterpret_cast 运算符可能很容易带来风险。 除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。

#include <iostream>
#include <Windows.h>
using namespace std;

class Animal {public: void cry() {cout << "动物叫" << endl;}};
class Dog : public Animal {public: void cry() {cout << "汪汪汪" << endl;}};
class Cat : public Animal {public: void cry() {cout << "喵喵喵" << endl;}};

int main(void){
	//用法一, 普通类型之间的转换
	int* p = reinterpret_cast<int*>(0x888888);
	int val = reinterpret_cast<int>(p);

	//用法二, 不同指针类型之间的转换, 和引用之间的转换
	Dog d1;
	Animal* a1 = reinterpret_cast<Animal*>(&d1);

	Dog* d2 = reinterpret_cast<Dog*>(a1);
	Dog* d3 = static_cast<Dog*>(a1);		//能使用static_cast, 尽量优先使用

	//Cat* c1 = static_cast<Cat*>(&d1);		//NO! 不同类型之间的转换, 不能使用static_cast
	Cat* c2 = reinterpret_cast<Cat*>(&d1);	//不同类型之间的转换, 可以使用reinterpret_cast

	system("pause");
	return 0;
}

dynamic_cast

  • 动态类型转换
  • 将一个基类对象指针cast到继承类指针,dynamic_cast 会根据基类指针是否真正指向继承类指针来做相应处理。失败返回null,成功返回正常cast后的对象指针;
  • 将一个基类对象引用cast 继承类对象,dynamic_cast 会根据基类对象是否真正属于继承类来做相应处理。失败抛出异常bad_cast
  • 注意:dynamic_cast在将父类cast到子类时,父类必须要有虚函数一起使用
#include <iostream>
#include <Windows.h>
using namespace std;

class Animal {
public:
	virtual void cry() = 0;
	virtual void play() = 0;
};

class Dog : public Animal {
public:
	void cry() {cout << "狗: 汪汪汪" << endl;}
	void play() { cout << "打个滚" << endl; }
};

class Cat : public Animal {
public:
	void cry() {cout << "猫: 喵喵喵" << endl;}
	void play() { cout << "爬上树" << endl; }
};


void animalPlay(Animal* ani) {
	ani->cry();
	Dog* dog = dynamic_cast<Dog*>(ani);
	if (dog) {
		dog->play();
	} else {
		cout << "不是狗, 别骗我!" << endl;
	}

	Cat* cat = dynamic_cast<Cat*>(ani);
	if (cat) {
		cat->play();
	} else {
		cout << "不是猫, 别骗我!" << endl;
	}
}

void animalPlay2(Animal& ani) {
	ani.cry();
	try {
		Dog& dog = dynamic_cast<Dog&>(ani);
		dog.play();
	} catch (std::bad_cast) {
		cout << "不是狗, 应该是下面的猫" << endl;
	}

	try {
		Cat& cat = dynamic_cast<Cat&>(ani);
		cat.play();
	} catch (std::bad_cast) {
		cout << "不是猫, 应该是上面的狗" << endl;
	}
}

int main(void){
	Dog *dog = new Dog();
	Animal* a1 = dog;
	//animalPlay(a1);

	Cat* cat = new Cat();
	a1 = cat;
	//animalPlay(a1);

	Dog dog2;
	animalPlay2(dog2);
	
	Cat cat2;
	animalPlay2(cat2);
	
	system("pause");
	return 0;
}

const_cast

去const属性。(仅针对于指针和引用)

#include <iostream>
#include <Windows.h>
using namespace std;

void test(const char* p) {
	//去const属性
	char* p1 = const_cast<char*>(p);
	p1[0] = 'A';
}

int main(void){
	char c1[] = "12345678";

	test(c1);

	cout << c1 << endl;		//输出 "A2345678"
	
	system("pause");
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++基础知识 - C++的类型转换 的相关文章

  • C++ 中的“int”默认是“signed long int”吗?

    Is int默认情况下signed long int in C 它是否依赖于平台和 或编译器 如果是这样 怎么办 EDIT 以下任何一项是否保证是重复的 signed short int signed int signed long int
  • 如何使用最小起订量模拟私有只读 IList 属性

    我试图嘲笑这个列表 private readonly IList
  • 是否有可能将 *.pdb 文件包含到发布版本中以查看错误行号?

    我做了一个项目 所有设置都是默认的 当我在调试模式 构建配置 调试 下运行它并遇到异常时 它转储到我的自定义日志记录机制 其中包含错误行号 但是当我运行发布构建时 记录相同的异常 没有行号 只有方法抛出和记录调用堆栈 是否有可能在发布配置
  • 在异步请求中使用超时回调

    我之前问过这个问题 但我将用提出的解决方案来完成这个问题 并提出另一个问题 我正在使用这个类来进行异步网络请求 http msdn microsoft com en us library system net webrequest aspx
  • 如何部署包含第三方 DLL 文件的 C# 应用程序?

    首先 我对部署了解不多 我希望我的问题有意义 我需要将 C 应用程序安装 部署到多个桌面 它需要一个第三方 DLL 文件 一个 C 库 lpsolve55 dll 对于那些感兴趣的人 它是一个免费的 MIP LP 求解器 请参阅 lpsol
  • 尽管浮点数相同,但它们并不相等? [复制]

    这个问题在这里已经有答案了 下面的程序输出This No is not same 当两个数字相同时为什么会这样做 void main float f 2 7 if f 2 7 printf This No is same else prin
  • 如何将 Visual-Studio 2010 切换到 c++11

    我是 c 编程新手 我想尝试 c 11 新功能 那么我要问的是如何切换 Visual studio 2010 才能编译 c 11 源代码 你可以参考这个表 VC10 中的 C 0x 核心语言功能 表格 http blogs msdn com
  • 多线程 - 比单线程慢

    当我使用多个线程而不是单线程运行程序时 它会变慢 不是应该更快吗 该程序应该遍历从起始目录开始的所有目录 并查找并打印所有名为 X 的文件 代码如下 while done pthread mutex lock lock if list is
  • C#生成的csv文件通过电子邮件发送嵌入到Lotus Note中电子邮件的底部

    我遇到了一个奇怪的问题 即使用 NET SmtpClient 通过电子邮件发送的 CSV 附件出现在电子邮件底部 而不是 Lotus Note 中的附件 我只是不知道如何解决这个问题 而且我无法访问客户端计算机 这使得调试非常困难 我可以采
  • 多个线程访问一个变量

    我在正在读的一本教科书中发现了这个问题 下面也给出了解决方案 我无法理解最小值怎么可能是 2 为什么一个线程不能读取 0 而所有其他线程都执行并写入 1 而无论是1还是2 最后写入的线程仍然必须完成自己的循环 int n 0 int mai
  • 为什么 rand() 总是返回相同的值? [复制]

    这个问题在这里已经有答案了 可能的重复 在C中生成随机数 https stackoverflow com questions 3067364 generating random numbers in c 使用 rand 生成随机数 http
  • 使用 catch all 字典属性将 json 序列化为对象

    我想使用 JSON net 反序列化为对象 但将未映射的属性放入字典属性中 是否可以 例如给定 json one 1 two 2 three 3 和 C 类 public class Mapped public int One get se
  • 从二进制文件读取字节到 long int

    我有两个问题 我有二进制文件的数据 我想使用 read 函数读取前 8 个字节以签署 long int 但我不能 你知道我该怎么做吗 如何直接读取一块数据到字符串中 我可以像所示那样阅读吗 前任 ifstream is is open te
  • 禁用实体框架的默认值生成(Code First)

    我数据库中有一个列不能为空 我想将其设置为默认值在数据库中 问题是实体框架似乎自己创建了一个默认值 例如 int gt 0 并且完全忽略了数据库中的默认值约束 有没有办法禁用实体框架的默认值 我发现您可以使用以下属性来装饰您的字段 Data
  • List 或其他类型上的 string.Join

    我想将整数数组或列表转换为逗号分隔的字符串 如下所示 string myFunction List
  • 删除数组时出现访问冲突异常

    删除分配的内存时 出现 访问冲突读取位置 异常 如下所示 我有一个针对 Visual Studio 2010 工具集 v100 C 编译器编译的本机 dll 我有一个针对它的托管 dll 包装器 它是针对工具集 v90 编译的 因为我想以
  • 如何在 SQLite 中检查数据库是否存在 C#

    我目前正在用 C 编写一个应用程序 并使用 sqlite 作为嵌入式数据库 我的应用程序在启动时创建一个新数据库 但如何让它检查数据库是否存在 如果它确实存在 我如何让它使用它 如果不存在如何创建一个新数据库 这是我到目前为止所拥有的 pr
  • C# 和断点 - 这里有魔术师吗?

    我有这个 public static void ByLinkText string text for var i 0 i lt 50 i try Setup Driver FindElement By LinkText text Click
  • 在两个点之间创建一条曲线,每个点都具有标准化向量

    因此 我需要一种写入方法来在两点之间创建一条曲线 每个点都有一个指向任意方向的归一化向量 我一直在尝试设计这样一种方法 但一直无法理解数学 在这里 由于一张图片胜过一千个文字 这就是我所需要的 在图中 矢量垂直于红线 我相信向量需要进行相同
  • boost::spirit::qi::语法和可变参数模板

    我在使用可变参数模板定义语法时面临一个问题 我首先定义一些包含在某些结构中的简单语法 例如纬度 经度 如下所示 include

随机推荐

  • 程序员mac开发环境配置

    拿了一台新的macbook pro 作为一个程序员 我把自己的开发环境给贴出来 1 输入法 先把苹果的系统自带的中文输入法 换成自己习惯的搜狗输入法 2 略 3 jdk 7u71 直接下载dmg文件安装 4 git 在terminal中 直
  • 中国职场女性领导者专题访谈

    导读 书写中国职场女性领导者并不容易 一不小心就会落入成功学后验主义窠臼 狭隘单一的价值评判 亦或是隐形性别偏见 但我们还是坚定地提笔 因为每一位女性领导者的成长历程 无论高光时刻还是黑暗片段 都会通过文字与读者产生连接 为其带来启示 而我
  • 服务器计算机性能测试,服务器平台计算性能工具Linpack服务器性能测试利器_一_.pdf...

    服务器平台计算性能工具Linpack服务器性能测试利器 一 pdf 产 品 技 术 服务器平台 文 赵吉志 计算性能工具Linpack 服务器性能测试利器 一 计算机硬件的不断升级带来了系统处理性能的持续提高 如何对平台的性能作出正确的判断
  • Linux基础(命令学习) ———从入坑到放弃1.0

    Linux文件 一 系统层次图 Linux文件类型 在Linux中一切都是文件 但文件都得有类型 shell 对命令的解释 cd pwd 查看当前的工作目录 Is 列表显示目录内容 alias 设置别名 du 统计目录及文件空间占用情况 m
  • SpringBoot的基本使用

    SpringBoot 目录 SpringBoot 一 SpringBoot简介 1 什么是SpringBoot 2 SpringBoot的优点 3 SpringBoot的缺点 二 SpringBoot的创建方式 1 基于官网的Initial
  • 【vue运行报错】There are multiple modules with names... 报错原因和解决办法

    项目场景 There are multiple modules with names that only differ in casing 项目运行时候报错如下 There are multiple modules with names t
  • Python中的__init__.py的高级用法

    刚开始学习编程 我们很少会关注这个文件 只知道一个目录中存在该文件 该目录就是一个package 不存在就是普通的目录 普通的目录在导入包时 pycharm并不会智能提示 Python中每新建一个package都会默认生成一个 init p
  • (一)app自动化测试环境搭建(mac+ios+airtest )

    环境搭建的效果如下 IOS手机屏幕显示Automation Running 电脑端airtest设备窗口上可以看到手机屏幕 以下是在mac电脑的搭建过程 只演示连接IOS真机部分 安卓机较为简单暂时省略 1 APP自动化测试工具介绍 Air
  • 半监督目标检测

    有监督目标检测 拥有大规模带标签的数据 包括完整的实例级别的标注 即包含坐标和类别信息 弱监督目标检测 数据集中的标注仅包含类别信息 不包含坐标信息 如图一 b 所示 弱半监督目标检测 数据集中拥有部分实例级别的标注 大量弱标注数据 模型希
  • MCU刷写

    1 个人电脑安装python2 7 2 用调试线连接个人电脑与控制器 3 控制器断电 数秒后上电 4 bootload2 py update s19两个文件放在一个文件夹内 5 ubuntu系统下 在当前文件夹下打开终端 输入 chmod
  • GD32F103使用DMA方式实现ADC0数据循环采集

    选择合适的DMA通道 ADC0使用ch0 brief configure the DMA peripheral param in none param out none retval none void dma config void AD
  • ST MCU Finder:MCU/MPU选型神器

    点击上方蓝字 关注我们 1 ST MCU Finder简介 ST MCU Finder 是 ST MCU生态系统中的选型工具 也内嵌在STM32CubeMX 和 STM32CubeIDE 中 具有相同的数据基础 可以通过在电脑端安装ST M
  • heartbeat mysql nfs 高可用mysql集群

    一 环境准备 二 拓扑结构 三 安装heartbeat 四 配置NFS服务 五 安装mysql 六 crm 配置资源 一 环境准备 操作系统 centos 6 4 x86 64 最小化安装 如使用yum 安装的方式 centos5 5 安装
  • Object类型数据转化为json字符串工具类

    Object类型数据转json字符串 package com xxxxx emis base util import com fasterxml jackson annotation JsonFilter import com faster
  • 2022Robocom(本科组)RC-u2 智能服药助手

    智能看护中很重要的环节是安排需要服药的老年人的服药计划 已知机器人需要照顾的某位老年人需要服用 N 种药物 但某些药物不宜间隔过短服用 比如降糖药一般遵医嘱日服 3 次 两次之间需要间隔至少 4 小时 当需要服用的药物比较多 医嘱比较复杂时
  • 深入理解PoW共识

    前言 上一篇文章中大概介绍了一下目前区块链应用中的几种常用的共识机制 本篇将重点聊一下区块链之一的PoW共识机制 以及它的实现原理和代码实现 PoW Proof of Work 工作量证明 其核心设计思路是提出求一个复杂度计算值的运算过程
  • 多播与广播原理分析及区别

    1 0 广播 广播的用途 假定服务器主机在本地局域网上 但不知道它的单播IP地址时对它进行定位 即进行资源发现 当有多个客户和单个服务器通信时 减少局域网上的数据流量 使用广播的因特网应用的例子 ARP协议通过链路层广播定位具有指定IP地址
  • RS485通信(Modbus)丢包解决经验(基于ARM/Linux和STM32平台)

    1 RS485通信属于半双工通信 即发送和接收不能同时进行 需要切换 一般定义一根GPIO做RTS切换 2 ARM Linux平台有Linux底层驱动做自动切换 比如应用程序发送完成后 一般会在底层驱动自动切换接收 3 但是STM32平台基
  • 【工作中常用工具类,提升开发效率】

    JDK常用工具类 JDK中常用工具类 集合工具类 Collections 数组工具类 Arrays 对象工具类 Objects 文件工具类 Files 路径工具类 Paths TimeUnit 线程sleet System JDK中常用工具
  • C++基础知识 - C++的类型转换

    类型转换使用建议 static cast静态类型转换 编译的时c 编译器会做编译时的类型检查 隐式转换 基本类型转换 父子类之间合理转换 若不同类型之间 进行强制类型转换 用reinterpret cast lt gt 进行重新解释 建 议