c++ 命名的强制类型转换
显式转换:显式将一种类型转换为另一种类型。
References:
与命名的强制类型转换相比,旧式的强制类型转换从表现形式上来说不那么清晰明了,容易被看漏,所以一旦转换过程出现问题,追踪起来也更加困难。
C++ 引入新的强制类型转换机制,主要是为了克服C语言强制类型转换的以下三个缺点:
- 没有从形式上体现转换功能和风险的不同。
例如,将 int 强制转换成 double 是没有风险的,而将常量指针转换成非常量指针,将基类指针转换成派生类指针都是高风险的,而且后两者带来的风险不同(即可能引发不同种类的错误),C语言的强制类型转换形式对这些不同并不加以区分。
将多态基类指针转换成派生类指针时不检查安全性,即无法判断转换后的指针是否确实指向一个派生类对象。
难以在程序中寻找到底什么地方进行了强制类型转换。
一、static_cast
是一种静态的转换,在编译期就能确定的转换,可以完成C语言中的强制类型转换中的大部分工作,但需要注意的是,它不能转换掉表达式的 const、volitale 或者 __unaligned 属性。
- 将较大的算术类型转换为较小的算术类型
double slope = static_cast<double>(j)/i;
相当于 (double)j/i
#include <iostream>
using namespace std;
class A
{
public:
operator int() { return 1; }
operator char*() { return NULL; }
};
int main()
{
A a;
int n;
char* p = "New Dragon Inn";
n = static_cast <int> (3.14); // n 的值变为 3
n = static_cast <int> (a); //调用 a.operator int,n 的值变为 1
p = static_cast <char*> (a); //调用 a.operator char*,p 的值变为 NULL
n = static_cast <int> (p); //编译错误,static_cast不能将指针转换成整型
p = static_cast <char*> (n); //编译错误,static_cast 不能将整型转换成指针
return 0;
}
一般来说,如果编译器发现一个较大的算术类型试图赋值给较小的类型,就会给出警告信息;但是当我们执行了显式的类型转换后,警告信息就会被关闭了。
添加const: 将非const转换为const。
将表达式转换成void类型,并将转换后的结果丢弃
int val = 110;
static_cast<void>(val);
- static_cast对于编译器无法自动执行的类型转换也非常有用, 可以用于void*和其他指针类型之间的转换。例如,我们可以使用static_cast找回存在于void*指针中的值。
void* p = &d; //任何非常量对象的地址都能存入void*
double* dp = static_cast<double*>(p);
static_cast 不能用于在不同类型的指针之间(如char*与int*之间)互相转换,也不能用于整型和指针之间的互相转换,当然也不能用于不同类型的引用之间的转换。因为这些属于风险比较高的转换。
可以用于类继承结构中基类和派生类之间指针或引用的转换,向上转型安全,向下转型由于没有动态类型检查,是不安全的。
如果涉及左值到右值、数组到指针或函数到指针的转换,也可以通过static_cast显式执行
std::move()的实现
二、dynamic_cast
适用于以下情况:我们想使用基类对象的指针或引用执行某个派生类操作并且该操作不是虚函数。
相比于 static_cast 的编译时转换, dynamic_cast 的转换还会在运行时进行类型检查,转换的条件也比较苛刻,必须有继承关系的类之间才能转换,并且在基类中有虚函数才可以,有一种特殊的情况就是可以把类指针转换成 void* 类型。
不能用于基本类型。
- RTTI:
实现运行时类型识别。运行时类型识别(run-time type identification,RTTI)的功能由两个运算符实现:
- typeid运算符,用于返回表达式的类型。
- dynamic_cast运算符,用于将基类的指针或引用安全地转换成派生类的指针或引用。
dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。 ** 可用于将基类的指针或引用安全地转换成派生类的指针或引用**。
有三种使用形式:
type通常应该是一个类类型,通常情况下应该含有虚函数。
e的类型必须符合以下三个条件中的任意一个:e的类型是目标type的公有派生类、e的类型是目标type的公有基类或者e的类型就是目标type的类型。如果符合,则类型转换可以成功。否则,转换失败。
- dynamic_cast<type*>(e) //e必须是一个有效的指针;
- dynamic_cast<type&>(e) //e必须是一个左值;
- dynamic_cast<type&&>(e) //e不能是左值;
- 在横向转换时指针发生了变化,可以看出 dynamic_cast 不是简单的数据强转,还进行了指针的偏移。
三、const_cast
将常量对象转换为非常量对象的行为:cast away the const. 实现有时需要对const对象进行修改。
const_cast 比较好理解,它用来去掉表达式的 const 修饰或 volatile 修饰。换句话说,const_cast 就是用来将 const/volatile 类型转换为非 const/volatile 类型。只有const_cast可以改变常量表达式的常量属性。
const_cast 不能去除变量的常量性,只能用来去除指向常数对象的指针或引用的常量性,且去除常量性的对象必须为指针或引用。
#include <iostream>
using namespace std;
int main(void) {
const int d = 2;
int* a = const_cast<int*>(&d);
*a = 3;
cout<<d<<endl;
return 0;
}
输出为:
2
这是因为使用变量d的语句在编译期就被替换为了2。
- 将 const 引用转换为同类型的非 const 引用,将 const 指针转换为同类型的非 const 指针时可以使用 const_cast 运算符。
#include <iostream>
using namespace std;
int main(void) {
int d = 2;
const int* a = &d;
int* b = const_cast<int*>(a);
cout<<*a<<endl;
cout<<*b<<endl;
*b = 3;
cout<<*a<<endl;
cout<<*b<<endl;
return 0;
}
输出:
2
2
3
3
四、 reinterpret_cast
- reinterpret_cast被用于不同类型指针或引用之间的转换,或者指针和整数之间的转换, 是对运算对象的二进制位的重新解释。
- 不同基础类型指针类型之间转换
int* ip;
char* pc = reinterpret_cast<char*>(ip);
我们必须牢记pc所指的真实对象是一个int而非字符,如果把pc当成普通的字符指针使用就可能在运行时发生错误。
基础类型指针与类对象指针之间的转换
将地址值转换成整数
- reinterpret_cast本质上依赖于机器。要想安全地使用reinterpret_cast必须对涉及的类型和编译器实现转换的过程都非常了解。
summary
- C/C++中不同数据类型进行运算或者赋值的时候会发生数据转换,这种转换有些是自动进行的,有些需要进行显示的强制类型转换
- 在C语言中强制类型转换写成(new_type_name) expression的形式,new_type_name 是要转换的目标类型,expression 是待转换的表达式
- 在C++中强制类型转换通过更明显的关键字来完成,分别是static_cast、 dynamic_cast, const_cast、 和 reinterpret_cast
- static_cast 是静态转换,在编译期完成完成转换,与C语言中的强制类型转换重合度最高
- dynamic_cast 是动态转换,在运行时转换会进行检查,必须用在有继承关系的多态结构中
- const_cast 是常量转换,用于取出指针或引用的常量属性,但是尽量通过设计杜绝它的使用场景
- reinterpret_cast 是一种内存数据的重新解释,比较原始,开发者使用它的时候应该明确的知道自己在做什么
————————————————
版权声明:本文为CSDN博主「AlbertS」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/albertsh/article/details/118663176
c++ 命名的强制类型转换的更多相关文章
- C++ Primer 有感(命名的强制类型转换)
C++四种强制类型转换的方法以及其应用场合,之前有看过这个知识点,但是,面试的时候怎么想也就没有写的很全面,于是,这里整理一下: C++中的四种强制类型转换除了具有C语言强制类型转换的功能外,还可提供 ...
- C++的几种强制类型转换
有时我们希望显式地将对象强制类型转换成另外一种类型.例如,如果想在下面的代码中执行浮点数除法: int i, j; double slope = i / j; 就要使用某种方法将i和/或j显式地转换成 ...
- 小猪猪逆袭成博士之C++基础篇(一)数据精度、强制类型转换、变量命名规则
小猪猪逆袭成博士之C++基础篇(一) 关键词: 数据精度.强制类型转换.变量命名规则 综述: 1.大多数编程语言通过两种方式来进一步补充其特征:一是赋予程序员自定义数据类型的权利(C++中的类):二是 ...
- 【JAVA】笔记(1)---JVM内存图;方法重载条件;输入方法;转义字符;强制类型转换;变量分类及区别;Java命名规范;
Java命名规范: 1.包:全部字母小写: 2.类+接口:所有单词的首字母大写: 3.变量+方法:第一个单词的首字母小写,其余单词首字母大写: 3.常量名:所有字母均大写,且用下划线" _ ...
- C++开发必看 四种强制类型转换的总结 [转]
一.C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a 二.C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. co ...
- C++开发必看 四种强制类型转换的总结
C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. const_cast ...
- c++的四种强制类型转换
http://hb.qq.com/a/20110722/001452.htm ...... C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是:TYPE b = (TYPE)a ...
- 四种强制类型转换的总结(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)很简单,不管什么类 ...
- 040_字符串连接符 041_条件运算符目 042_运算符优先级_逻辑与或优先问题 043_自动类型转化 044_强制类型转换 045_基本类型常见错误_溢出_L问题
040_字符串连接符 package test_package; /** * 字符串运算符 * @author * */public class TestOperator05 { public sta ...
随机推荐
- yb课堂之跨域配置 《二十三》
CorsInterceptor.java package net.ybclass.online_ybclass.interceptor; import org.springframework.http ...
- webpack4.15.1 学习笔记(九) — 11个基础的插件使用
目录 html-webpack-plugin clean-webpack-plugin webpack-manifest-plugin HotModuleReplacementPlugin(内置) m ...
- 说说XXLJob分片任务实现原理?
XXL Job 是一个开源的分布式任务调度平台,其核心设计目标是开发迅速.学习简单.轻量级.易扩展的分布式任务调度框架. 这两天咱们开发的 AI Cloud 项目中,也使用到了 XXL Job 来执行 ...
- oeasy教您玩转vim - 7 - # 从头插入
另存与保存 回忆上节课内容 上次我们学会了另存为命令 : saveas {file} 还有这个直接保存命令 : w 真的可以把修改存了 下面我们来研究插入命令的细节. 插入命令 首先我们可以查询这个插 ...
- 如何在 Vue 和 JavaScript 中截取视频任意帧图片
如何在 Vue 和 JavaScript 中截取视频任意帧图片 大家好!今天我们来聊聊如何在 Vue 和 JavaScript 中截取视频的任意一帧图片.这个功能在很多场景下都非常有用,比如视频编辑. ...
- NSSCTF———Web(sql注入)
[LitCTF 2023]这是什么?SQL !注一下 ! [SWPUCTF 2022 新生赛]ez_sql [GXYCTF 2019]BabySqli 点击右下角文章可跳转 [LitCTF 2023] ...
- 自写ApiTools工具,功能参考Postman和ApiPost
近日在使用ApiPost的时候,发现新版本8和7不兼容,也就是说8不支持离线操作,而7可以. 我想说,我就是因为不想登录使用才从Postman换到ApiPost的. 众所周知,postman时国外软件 ...
- nacos启动失败:No DataSource set
通过docker查看nacos的日志发现nacos好端端的突然不能用了 docker logs nacos 报错后说是no datasource set,我看了我在docker里的MySQL是正常启动 ...
- RHCA rh442 002 监控工具 脏页 块设备名 缓存
sar 看某一个时间的数据 sar -d 1 5 与iostat类似 计算机识别设备按编号识别 0-15预留出 8 为iscsi设备 做一个块设备名 名字不重要是给人看的,重要的是编号 8 17(主编 ...
- 【Java】再谈Springboot 策略模式
第一次使用策略模式是一年前的一个项目: https://www.cnblogs.com/mindzone/p/16046538.html 当时还不知道Spring支持集合类型的自动装配 在最近一个项目 ...