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 ...
随机推荐
- 将虚拟机跑在ceph之中
目录 openStack对接ceph 1. cinder对接ceph 1.1 ceph创建存储池 1.2 ceph授权 1.3 下发ceph文件 1.4 修改globals文件 1.5 部署cinde ...
- mysql 忘记root密码怎么办?
忘记root可以跳过grant table来登录 1.打开命令行输入以下命令 mysqld -nt --grant-skip-tables 2.在打开一个新命令行,输入以下命令可以登录, mysql ...
- Git的存储原理
目录 Git 设计原理 Git vs SVN Git 存储模型 .git 目录结构 Git 基本数据对象 Git 包文件 Git 引用 Git 设计原理 概括的讲,Git 就是一个基于快照的内容寻址文 ...
- 如何自动实现本地AD中禁用的用户从地址列表中隐藏掉?
我的博客园:https://www.cnblogs.com/CQman/ 如何自动实现本地AD中禁用的用户从地址列表中隐藏掉? 需求信息: 用户本地AD用户通过ADConnect同步到O365,用户想 ...
- 神经网络之卷积篇:详解计算机视觉(Computer vision)
详解计算机视觉 计算机视觉是一个飞速发展的一个领域,这多亏了深度学习.深度学习与计算机视觉可以帮助汽车,查明周围的行人和汽车,并帮助汽车避开它们.还使得人脸识别技术变得更加效率和精准,即将能够体验到或 ...
- golang对遍历目录操作的优化
一转眼go1.23都快发布了,时间过得真快. 不过今天我们把时间倒流回三年半之前,来关注一个在go1.16引入的关于处理目录时的优化. 对于go1.16的新变化,大家印象最深的可能是io包的大规模重构 ...
- 从web2的用户名密码登录到web3的钱包签名认证
Web2 都有哪些常用的认证场景 早期我们使用网页类 Web2 应用时,大多采用账号 + 密码的认证方式访问.为了方便很多网站设置的都是相同的密码(这很不安全). 随着移动应用的普及,慢慢我们习惯了手 ...
- Tomcat日志信息有乱码的处理方法
1.问题描述 1.1.Idea中的tomcat日志有乱码 1.2.直接启动tomcat的日志有乱码 1.3.原因分析 问题是由于tomcat使用的编码和操作系统使用的编码不一致导致: Windows1 ...
- 【IDEA】创建Maven工程
当前工程,点new - project 选Maven,不需要点选什么骨架创建,骨架创建要下载大量依赖,生成时间太长, 空Maven的目的是让我们自己了解这个项目结构,需要什么依赖再加什么依赖 框线内的 ...
- 从.net开发做到云原生运维(四)——.net core的微服务开发
1. .net 6.0项目模板变更 在.net 5和.net 3.1的时候,asp.net core项目模板里有个Program类和Startup类,在.net 6中引入了一个最小api的项目模板,在 ...