C++ 引入了四种功能不同的强制类型转换运算符以进行强制类型转换:static_cast、reinterpret_cast、const_cast和dynamic_cast,当然C++为保持与C的兼容,也保留了C语法中强制类型转换运算符的写法。

  C++引入新的强制类型转换机制,主要为是为克服C语言强制类型转换的三个主要的切点:

  1、没有从形式上体现转换功能和风险的不同

    例如,将 int 强制转换成 double 是没有风险的,而将常量指针转换成非常量指针,将基类指针转换成派生类指针都是高风险的,而且后两者带来的风险不同(即可能引发不同种类的错误),C语言的强制类型转换形式对这些不同并不加以区分。

  2、将多态基类指针转换成派生类指针时不检查安全性,即无法判断转换后的指针是否确实指向一个派生类对象

  3、难以在程序中寻找到底什么地方进行了强制类型转换

  而用 C++ 的方式,则只需要查找_cast字符串就可以了。甚至可以根据错误的类型,有针对性地专门查找某一种强制类型转换。例如,怀疑一个错误可能是由于使用了 reinterpret_cast 导致的,就可以只查找reinterpret_cast字符串。

  C++强制类型转换运算符的用法如下:

强制类型转换运算符 <要转换到的类型> (待转换的表达式)

  例如:

double d = static_cast <double> (3*5);  //将 3*5 的值转换成实数

  现在来说下这四种强制类型转换运算符

  1、static_cast

  作用:static_cast用于比较“自然”和低风险的转换,比如整型和浮点型、字符型之间的转换。另外,如果对象所属的类重载了强制类型运算符T(如T是int、int*或其他类型名),则static_cast也能用来进行对象到T类型的转换。(但不能用于不同类型指针、整型与指针等这些高风险的转换中)

  2、reinterpret_cast

  作用:reinterpret_cast用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳指针的整数类型的转换(高风险的转换)。转换时,执行的是逐个比特复制的操作。

  这种转换提供了很强的灵活性,但转换的安全性只能由程序员的细心来保证了。例如,程序员执意要把一个 int* 指针、函数指针或其他类型的指针转换成 string* 类型的指针也是可以的,至于以后用转换后的指针调用 string 类的成员函数引发错误,程序员也只能自行承担查找错误的烦琐工作:(C++ 标准不允许将函数指针转换成对象指针,但有些编译器,如 Visual Studio 2010,则支持这种转换)。

  reinterpret_cast体现了 C++ 语言的设计思想:用户可以做任何操作,但要为自己的行为负责。

  3、const_cast

   作用:const_cast仅用于进行去除const属性的转换,它也是四个强制类型转换运算符中唯一一个能够去除const属性的运算符

const string s = "Inception";
string& p = const_cast <string&> (s);
string* ps = const_cast <string*> (&s); // &s 的类型是 const string*

  4、dynamic_cast

  用reinterpret_cast可以将多态基类(包括虚函数的基类)的指针强制转换成派生类的指针,但这种转换不检查安全性,即不检查转换后的指针是否确实指向一个派生类对象。dynamic_cast专门用于将多态基类的指针或引用强制转换为派生类的指针或引用,而且能够检查转换的安全性。对于不安全的指针转换,转换结果范围NULL指针。

  dynamic_cast 是通过“运行时类型检查”来保证安全性的。dynamic_cast 不能用于将非多态基类的指针或引用强制转换为派生类的指针或引用——这种转换没法保证安全性,只好用 reinterpret_cast 来完成。

#include <iostream>
#include <string>
using namespace std;
class Base
{ //有虚函数,因此是多态基类
public:
virtual ~Base() {}
};
class Derived : public Base { };
int main()
{
Base b;
Derived d;
Derived* pd;
pd = reinterpret_cast <Derived*> (&b);
if (pd == NULL)
//此处pd不会为 NULL。reinterpret_cast不检查安全性,总是进行转换
cout << "unsafe reinterpret_cast" << endl; //不会执行
pd = dynamic_cast <Derived*> (&b);
if (pd == NULL) //结果会是NULL,因为 &b 不指向派生类对象,此转换不安全
cout << "unsafe dynamic_cast1" << endl; //会执行
pd = dynamic_cast <Derived*> (&d); //安全的转换
if (pd == NULL) //此处 pd 不会为 NULL
cout << "unsafe dynamic_cast2" << endl; //不会执行
return 0;
}

输出结果:

unsafe dynamic_cast1

第 20 行,通过判断 pd 的值是否为 NULL,就能知道第 19 行进行的转换是否是安全的。第 23 行同理。

如果上面的程序中出现了下面的语句:

Derived & r = dynamic_cast <Derived &> (b);

那该如何判断该转换是否安全呢?不存在空引用,因此不能通过返回值来判断转换是否安全。C++ 的解决办法是:dynamic_cast 在进行引用的强制转换时,如果发现转换不安全,就会拋出一个异常,通过处理异常,就能发现不安全的转换。

参考:http://c.biancheng.net/view/410.html

C++强制类型转换运算符(static_cast、reinterpret_cast、const_cast和dynamic_cast)的更多相关文章

  1. 类型转换操作符static_cast、const_cast、dynamic_cast、reinterpret_cast

    一.static_cast 对于类型转换,我们常常这么做: (type) expression 引进了static_cast类型转换操作符后,我们只需这样做: static_cast<type& ...

  2. C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast

    1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为: (type-id)expression//转换格式1 type-id(expression)//转换格式2 ...

  3. C++类型转换运算符 static_cast,dynamic_cast,reinterpret_cast,const_cast

    类型转换是一种让程序猿可以临时或永久性改变编译器对对象的解释机制.可改变对象解释方式的运算符称为类型转换运算符. 为何须要进行类型转换 通常为了实现使用不同环境的个人和厂商编写的模块可以相互调用和协作 ...

  4. static_cast 、const_cast、dynamic_cast、reinterpret_cast 关键字简单解释

    static_cast .const_cast.dynamic_cast.reinterpret_cast 关键字简单解释: Static_cast 静态类型转换 ①用于类层次结构中基类(父类)和派生 ...

  5. [转]C++重载()(强制类型转换运算符)

    在 C++ 中,类型的名字(包括类的名字)本身也是一种运算符,即类型强制转换运算符. 类型强制转换运算符是单目运算符,也可以被重载,但只能重载为成员函数,不能重载为全局函数.经过适当重载后,(类型名) ...

  6. C++中的四种类型转换运算符static_cast、dynamic_cast、const_cast和reinterpret_cast的使用

    1.上一遍讲述了C语言的隐式类型转换和显示类型转换,C语言之所以增加强制类型转换,就是为了强调转换的风险性,但这种强调风险的方式是比较粗放了,粒度比较大,它并没有表明存在什么风险,风险程度如何. 2. ...

  7. C++强制类型转换操作符 static_cast

    static_cast是一个强制类型转换操作符.强制类型转换,也称为显式转换,C++中强制类型转换操作符有static_cast.dynamic_cast.const_cast.reinterpert ...

  8. C++语言基础(24)-四种类型转换运算符(static_cast、dynamic_cast、const_cast和reinterpret_cast)

    一.static_cast static_cast 只能用于良性转换,这样的转换风险较低,一般不会发生什么意外,如: #include <iostream> #include <cs ...

  9. C++之强制类型转换

     C++ Code  12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...

  10. C++类型转化:static_cast,reinterpret_cast,dynamic_cast,const_cast

    类型转换名称和语法 C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. ...

随机推荐

  1. 动手学大模型应用开发,第4天:Prompt设计

    第一章.Prompt 设计的原则和技巧 LLM 时代 prompt 这个词对于每个使用者和开发者来说已经听得滚瓜烂熟,那么到底什么是 prompt 呢?简单来说,prompt(提示) 就是用户与大模型 ...

  2. Java开发中long类型转换json传递到前端后精度丢失问题

    将文章的id由long类型手动改为String类型(需要修改表结构); 可以使用Jackson进行序列化解决

  3. Winform ShowDialog如何让先前Show的窗体可以交互

    背景描述 最近项目中有一个需求,全局有一个共用的窗体,能够打开不同模块的报告,由于需要兼容不同模块,代码复杂,启动速度慢.优化方案为将窗体启动时就创建好,需要查看报告时,使用此单例弹窗加载不同模块下的 ...

  4. 解决win11输入法自定义短语有多个当前日期只有最后一个生效

    由于win11自定义短语保存机制问题导致只有最后一个当前日期短语生效** 1.首先找到自定义短语存储文件的具体路径:%AppData%\Microsoft\InputMethod\Chs\ 拼音输入法 ...

  5. @autowired注解报错原因及解决办法

    @autowired 注入dao层的时候,标红报错,但不影响编译使用 按照严格的spring注解方式在dao层加入@Repository注解

  6. 基于Element的el-input实现一个可以显示千分位符的金额输入框

    直接上代码 1 <template> 2 <!-- 定义一个 Element UI 的输入框组件 --> 3 <el-input 4 v-model="form ...

  7. useSlots-TS

    import {useSlots, VNode} from 'vue'; export const useGetSlots = () => { const slots = useSlots(); ...

  8. Mac 干净彻底地卸载 MySQL

    前言 卸载MySQL,首先得知道MySQL的路径.默认的话是在/usr/local文件夹下的. 在系统偏好设置面板中可以看到之前安装的MySQL,此时若想卸载MySQL,可以按照如下步骤来. 之前安装 ...

  9. golang定时器函数 每隔几分钟执行一个函数

    延时调用 AfterFunc go function() func function() { // TODO 具体逻辑 // 每5分钟执行一次,递归调用自己 time.AfterFunc(5*time ...

  10. 如何写自己的springboot starter?自动装配原理是什么?

    如何写自己的springboot starter?自动装配原理是什么? 官方文档地址:https://docs.spring.io/spring-boot/docs/2.6.13/reference/ ...