c++的四种强制类型转换:static_cast   dynamic_cast   const_cast    reinterpret_cast

2023-05-16

c++的四种强制类型转换为:static_cast   dynamic_cast   const_cast    reinterpret_cast

c++相对于c的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。

c++中风格是static_cast<type>(content)。它能更清楚的表明它们要干什么。

程序员也可以更直观的立即知道一个强制转换的目的。

static_cast:可以实现c++中内置基本数据类型之间相互转换。

   int C = static_cast<int>(7.889);

如果涉及到类的话,static_cast只能在有相互联系的类型中进行相互转换,不一定包含虚函数。

const_cast:其操作不能在不同的种类间转换,相反,它仅仅能把它作用的表达式,转换常量。

                   它可以使一个本来不是const的类型转换成const类型,或者把const属性去掉

 

reintepret_cast:(重新解释的计算)有着和C风格的强制转换同样的能力。他可以转化任何内置的数据类型为其他的任何数据类型,也可以转化任何指针类型为其他类型。他深灰可以转化内置的数据类型为指针,无需考虑类型安或常量的情形。不到万不得已绝对不用。

 

dynamic_cast:(动态的计算)

 (1)其他三种都是编译时完成的,,而它是运行时处理的,运行时要进行类型检查。

 (2)不能用于内置的基本数据类型的强制转换。

 (3)转换如果成功的话返回的是指向类指针或引用,转换失败的话侧翻会NULL。

 (4)使用dynamic_cast进行转化的基类中一定要有虚函数,否则编译不通过。

       需要检测有虚函数的原因:类中存在虚函数类中存在虚函数,就说明它有想要让基类指针或引用指向子类对象的情况,此时转换才有意义。

 (5)类的转换时:在类的层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的,在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
 

dynamic_cast主要用于“安全地向下转型(父类转换成子类)

这时本质上是:使用了一个父类指针指向子类对象,然后将这个指向子类对象的父类指针强制转换成子类指针。

Base * base = new Derived;

Derived* der = dynamic_cast<Derived*>(base);

怎么样?是不是很绕口?

dynamic_cast用于类继承层次间的指针或引用转换。主要还是用于执行“安全的向下转型(safe downcasting)”,也即是基类对象的指针或引用转换为同一继承层次的其他指针或引用。

至于“向上转型”(即派生类指针或引用类型转换为其基类类型),本身就是安全的,尽管可以使用dynamic_cast进行转换,但这是没必要的, 普通的转换已经可以达到目的,毕竟使用dynamic_cast是需要开销的。

 

class Base
{
public:
    Base(){};
    virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
    Derived(){};
    void Show(){cout<<"This is Derived class";}
};
int main()
{    
    Base *base ;
    Derived *der = new Derived;
    //base = dynamic_cast<Base*>(der); //正确,但不必要。
    base = der; //先上转换总是安全的
    base->Show(); 
    system("pause");
}
  • dynamic_cast与继承层次的指针

对于“向下转型”有两种情况。一种是基类指针所指对象是派生类类型的,这种转换是安全的;另一种是基类指针所指对象为基类类型,在这种情况下dynamic_cast在运行时做检查,转换失败,返回结果为0;

说明:有继承关系的情况下,子类向父类dynamic_cast转换(向上转型),是可行的,

但是父类向子类dynamic_cast转换(向下转型),会失败

 

#include "stdafx.h"
#include<iostream>
using namespace std;

class Base
{
public:
    Base(){};
    virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
    Derived(){};
    void Show(){cout<<"This is Derived class";}
};
int main()
{    
    //这是第一种情况
    Base* base = new Derived;
    if(Derived *der= dynamic_cast<Derived*>(base))
    {
        cout<<"第一种情况转换成功"<<endl;
        der->Show();
        cout<<endl;
    }
    //这是第二种情况
    Base * base1 = new Base;
    if(Derived *der1 = dynamic_cast<Derived*>(base1))
    {
        cout<<"第二种情况转换成功"<<endl;
        der1->Show();
    }
    else 
    {
        cout<<"第二种情况转换失败"<<endl;
    }

    delete(base);
    delete(base1);
    system("pause");
}

 

  •  dynamic_cast和引用类型

在前面的例子中,使用了dynamic_cast将基类指针转换为派生类指针,也可以使用dynamic_cast将基类引用转换为派生类引用。

同样的,引用的向上转换总是安全的:

    Derived c;
    Derived & der2= c;
    Base & base2= dynamic_cast<Base&>(der2);//向上转换,安全
    base2.Show();

所以,在引用上,dynamic_cast依旧是常用于“安全的向下转型”。与指针一样,引用的向下转型也可以分为两种情况,与指针不同的是,并不存在空引用,所以引用的dynamic_cast检测失败时会抛出一个bad_cast异常:

int main()
{    
    //第一种情况,转换成功
    Derived b ;
    Base &base1= b;
    Derived &der1 = dynamic_cast<Derived&>(base1);
    cout<<"第一种情况:";
    der1.Show();
    cout<<endl;

    //第二种情况
    Base a ;
    Base &base = a ;
    cout<<"第二种情况:";
    try{
        Derived & der = dynamic_cast<Derived&>(base);
    }
    catch(bad_cast)
    {
        cout<<"转化失败,抛出bad_cast异常"<<endl;
    }
    system("pause");
}

 

  • 使用dynamic_cast转换的Base类至少带有一个虚函数

    当一个类中拥有至少一个虚函数的时候,编译器会为该类构建出一个虚函数表(virtual method table),虚函数表记录了虚函数的地址。如果该类派生了其他子类,且子类定义并实现了基类的虚函数,那么虚函数表会将该函数指向新的地址。虚表是C++多态实现的一个重要手段,也是dynamic_cast操作符转换能够进行的前提条件。当类没有虚函数表的时候(也即一个虚函数都没有定义),dynamic_cast无法使用RTTI,不能通过编译(个人猜想...有待验证)。

  当然,虚函数表的建立对效率是有一定影响的,构建虚函数表、由表查询函数 都需要时间和空间上的消耗。所以,除了必须声明virtual(对于一个多态基类而言),不要轻易使用virtual函数。对于虚函数的进一步了解,可以查看《Effective C++》

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++的四种强制类型转换:static_cast   dynamic_cast   const_cast    reinterpret_cast 的相关文章

  • 《心流》——每天十分钟,解读完本书

    心流 每天十分钟 xff0c 解读完本书 你好 xff01 这里是 每天十分钟 xff0c 解读完本书 xff0c 我是财哥哥 xff0c 今天为你解读的是 心流 xff0c 作者是米哈里 契克森米哈赖 他是积极心理体验这一领域的权威学者
  • SourceInsight4.0的使用

    转自 xff1a https blog csdn net qq 39660930 article details 77499455 一 项目管理 1 新建一个项目 快捷键Alt 43 Shift 43 N可以打开新建项目对话框 xff0c
  • 输入一个英文句子,翻转句子中的单词,要求单词内的字符顺序不变。 如:I am a student. 转换成 student. a am I

    输入一个英文句子 xff0c 翻转句子中的单词 xff0c 要求单词内的字符顺序不变 如 xff1a I am a student 转换成 student a am I 算法分析 xff1a 1 通过ReverseString xff08
  • OpenMLDB开源社区贡献者体系今日发布

    关于OpenMLDB OpenMLDB 是一个开源机器学习数据库 xff0c 提供企业级 FeatureOps 全栈解决方案 OpenMLDB 致力于闭环解决 AI 工程化落地的数据治理难题 xff0c 并且已经在上百个企业级人工智能场景中
  • 排序算法

    影响排序算法性能的几个要素 xff1a 1 时间性能 2 辅助空间 3 算法的复杂性 直接插入排序算法的基本操作是将一个记录插入到已经排好序的有序表中 xff0c 从而得到一个新的 xff0c 记录数增加一的有序表 void InsertS
  • c语言常用小知识点总结1

    define 用来定义宏常量 格式 xff1a define 标识符 大写字母 常量 define PI 3 14 注意后面是不加 分号的 常用字母的ASCII码 39 a 39 61 97 39 A 39 61 65 39 0 39 61
  • 数据结构学习笔记1

    程序设计 61 数据结构 43 算法 谈谈算法 数据结构与算法是 好基友 xff0c 如果单独谈数据结构 xff0c 或者单独谈算法是没什么意义的 来一个牛叉的算法吧 xff01 计算1 43 2 43 3 43 4 43 100 xff0
  • Oracle面试题附带答案

    1 你要对操纵Oracle数据库中的数据 下列哪个选项表示Oracle中select语句的功能 xff0c 并且不需要使用子查询 xff08 C xff09 A xff0e 可以用select语句改变Oracle中的数据 B xff0e 可
  • C结构体中数据的内存对齐问题

    转自 xff1a http www cnblogs com qwcbeyond archive 2012 05 08 2490897 html 32位机一般默认4字节对齐 xff08 32位机机器字长4字节 xff09 xff0c 64位机
  • 解决codeblocks无法调试的问题

    错误提示 xff1a ERROR You need to specify a debugger program in the debuggers 39 s settings For MinGW compilers it 39 s 39 gd
  • 求出现在字符串1而没有出现在字符串2中的字符

    编写一个函数 xff0c 它的功能是将未在字符串s中出现 xff0c 而在字符串t中出现的字符 xff0c 型参一个新的字符串放在u中 xff0c u中的字符按原字符的顺序排列 xff0c 但要去掉重复字符 至少会想到去考察t xff0c
  • 什么情况下需要建立索引? 索引的作用?为什么能够提高查询速度?(索引的原理) 索引有什么副作用吗?

    https www cnblogs com Berryxiong p 6249427 html 为什么能够提高查询速度 xff1f 索引就是通过事先排好序 xff0c 从而在查找时可以应用二分查找等高效率的算法 一般的顺序查找 xff0c
  • 100w测试数据,为什么加了索引查询反而变慢了?

    建表 xff1a create table tb test fval varchar 50 插入测试数据 xff1a DELIMITER CREATE DEFINER 61 96 root 96 64 96 localhost 96 PRO
  • linux环境下使用gdb调试c和c++ 学习笔记

    第二十三课 xff1a GDB简介 哔哩哔哩 bilibili gdb调试 xff1a 1 gcc a c b c c c o app g g 编译器会保留函数名和变量名 2 启动gdb gdb 可执行程序的名字 xff08 gdb app
  • ubuntu下eth0网卡信息不见了

    ubuntu终端下命令ifconfig的问题解决 问题一 ifconfig之后只显示lo 没有看到eth0 问题二 ifconfig之后显示eth0 xff0c 但是没有显示静态IP地址 xff0c 即无inet 地址 广播 掩码 问题三
  • 计算机指令

    指令系统的设计原则包括 xff1a 完备性 xff1a 该有的都要有 有效性 xff1a 简洁 加速常用操作 没有歧义 规整性 xff1a 对称 均匀 一致 xff08 简单源于规整 xff09 兼容性 xff1a 之前 之后的都能用 下面
  • shell基础学习笔记1

    shell是什么 xff1f shell是一个命令解释器 xff0c 他为用户提供了一个向linux内核发送请求以便运行程序的界面系统级程序 xff0c 用户可以用shell来启动 挂起 停止甚至编写一些程序 其实就是输入命令的那个交互界面
  • linux达人养成学习笔记1

    2 4 分区之分区设备文件名与挂载 1 swap分区 xff0c 没有挂载点 xff0c 是文件系统类型 xff08 交换分区 xff0c 电脑内存 lt 4G xff0c 可分为内存2倍 xff1b gt 4G分同等大小 xff09 2
  • shell编程之变量学习小结

    在Bash中 xff0c 变量的默认类型都是字符串型 变量的分类 1 用户自定义变量 xff1a 变量可以自定义 xff0c 但是对系统生效的环境变量名和变量作用是固定的 2 环境变量 xff1a 这种变量中主要保存的是和系统操作环境相关的
  • 程序员的自我修养

    1 Provide Options Don 39 t make lame Excuses 提供各种选择 xff0c 不要找蹩脚的借口 2 Don 39 t live with Broken Windows 不要容忍破窗户 3 Be a ca

随机推荐