static_cast和dynamic_cast

C++的强制类型转换,除了继承自C语言的写法( (&#x76EE;&#x6807;&#x7C7B;&#x578B;)&#x8868;&#x8FBE;&#x5F0F;)之外,还新增了4个关键字,分别是: static_castdynamic_castconst_castreinterpret_cast。用法: xxx_cast<目标类型>(&#x8868;&#x8FBE;&#x5F0F;)<!--目标类型-->。由于后两者的使用频率较少,尤其是 reinterpret_cast的风险性很高,所以就不展开讲了。这里主要将 static_castdynamic_cast

static_cast

解释

所谓static_cast,顾名思义,就是静态的转换,是在编译期间就能确定的转换。

主要用途

  1. 用于基本数据类型之间的转换。
#include

using namespace std;

int main()
{
    float f = 5.67;
    auto i = static_cast(f);
    cout << i << endl;  // 输出结果:5
    return 0;
}
  1. 用于有转换关系的类之间的转换。
#include

using namespace std;

class Src
{
public:
    void foo()
    {
        cout << "This is Src" << endl;
    }
};

class Dest
{
public:
    /** 类型转换构造函数 */
    Dest(const Src &from)
    {
        cout << "Converting from Src to Dest" << endl;
    }

    void foo()
    {
        cout << "This is Dest" << endl;
    }
};

int main()
{
    Src src;
    auto dst = static_cast(src);  // 输出结果:Converting from Src to Dest
    dst.foo();  // 输出结果:This is Dest
}
  1. 用于在类继承体系中 指针或引用上行转换(即派生类到基类的转换)。如果用作下行转换(即基类到派生类的转换),由于不会动态的检查指针或引用是否真正指向派生类对象,因此不安全,要用到稍后要讲的 dynamic_cast
#include

using namespace std;

class Base
{
public:
    void foo()
    {
        cout << "This is Base" << endl;
    }
};

class Derived : public Base
{
public:
    void foo()
    {
        cout << "This is Derived" << endl;
    }
};

void test_upcast()
{
    Derived derived;
    Derived *pDerived = &derived;
    auto pBase = static_cast(pDerived);
    pBase->foo();  // 输出结果:This is Base
}

void test_downcast()
{
    Base base;
    Base *pBase = &base;
    auto pDerived = static_cast(pBase);  // 不安全:pa并没有真正指向B类对象
    pDerived->foo();  // 输出结果:This is Derived。这里虽然输出了结果,但是不安全
}

int main()
{
    test_upcast();
    test_downcast();
    return 0;
}

dynamic_cast

解释

所谓dynamic_cast,顾名思义就是动态的转换,是一种能够在运行时检查安全性的转换。

使用条件:

  1. 基类必须有虚函数。
  2. 只能转引用或指针。

主要用途

用于继承体系中的上行或下行转换。上行转换跟 static_cast是一样的;下行转换会在运行时动态判断。如果目标类型并没有指向对象的实际类型,那么:

  1. 指针的转换会返回 nullptr
  2. 引用的转换会抛出 std::bad_cast异常
#include

using namespace std;

class Base
{
public:
    virtual void foo()
    {
        cout << "This is Base" << endl;
    }
};

class Derived : public Base
{
public:
    void foo() override
    {
        cout << "This is Derived" << endl;
    }
};

/** Derived * -> Base * */
void test_upcast_ptr()
{
    Derived derived;
    Derived *pDerived = &derived;
    auto base = dynamic_cast(pDerived); // 尝试将派生类指针转换为基类指针
    if (base)
    {
        cout << "Derived * -> Base * was successful" << endl;
    }
    else
    {
        cout << "Derived * -> Base * failed" << endl;
    }
}

/** Base * -> Derived * */
void test_downcast_ptr1()
{
    Derived derived;
    Base *pBase = &derived; // 基类指针指向派生类对象
    auto pDerived = dynamic_cast(pBase); // 尝试将指向派生类对象的基类指针转换为派生类指针
    if (pDerived)
    {
        cout << "Base * -> Derived * was successful" << endl;
    }
    else
    {
        cout << "Base * -> Derived * failed" << endl;
    }
}

/** Base * -> Derived * */
void test_downcast_ptr2()
{
    Base base;
    Base *pBase = &base;
    auto derived = dynamic_cast(pBase); // 尝试将指向基类对象的基类指针转换为派生类指针
    if (derived)
    {
        cout << "Base * -> Derived * was successful" << endl;
    }
    else
    {
        cout << "Base * -> Derived * failed" << endl;
    }
}

/** Derived & -> Base & */
void test_upcast_ref()
{
    Derived derived;
    Derived &refDerived = derived;
    try
    {
        auto &base = dynamic_cast(refDerived); // 尝试将派生类引用转换为基类引用
        cout << "Derived & -> Base & was successful" << endl;
    }
    catch (bad_cast &)
    {
        cout << "Derived & -> Base & failed" << endl;
    }
}

/** Base & -> Derived & */
void test_downcast_ref1()
{
    Derived derived;
    Base &refBase = derived; // 基类引用指向派生类对象
    try
    {
        auto &refDerived = dynamic_cast(refBase); // 尝试将指向派生类对象的基类引用转换为派生类引用
        cout << "Base & -> Derived & was successful" << endl;
    }
    catch (bad_cast &)
    {
        cout << "Base & -> Derived & failed" << endl;
    }
}

/** Base & -> Derived & */
void test_downcast_ref2()
{
    Base base;
    Base &refBase = base;
    try
    {
        auto &refDerived = dynamic_cast(refBase); // 尝试将指向基类对象的基类引用转换为派生类引用
        cout << "Base & -> Derived & was successful" << endl;
    }
    catch (bad_cast &)
    {
        cout << "Base & -> Derived & failed" << endl;
    }
}

int main()
{
    test_upcast_ptr();     // Derived * -> Base * was successful
    test_downcast_ptr1();  // Base * -> Derived * was successful
    test_downcast_ptr2();  // Base * -> Derived * failed
    test_upcast_ref();     // Derived & -> Base & was successful
    test_downcast_ref1();  // Base & -> Derived & was successful
    test_downcast_ref2();  // Base & -> Derived & failed
}

Original: https://www.cnblogs.com/YWT-Real/p/16717930.html
Author: YWT_Real
Title: static_cast和dynamic_cast

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/604677/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Java 字符串Split方法的一个坑

    java字符串的split,只传一个参数,后面空白的字符串会被忽略: 输出结果是 [ab, c]。 解决方法是split第二个参数传一个负数,例如 输出 [ab, c, , ]。 …

    数据结构和算法 2023年6月16日
    074
  • C++:接送旅客

    时间限制:1.00sec 内存限制:128MB 题目描述: 现在,你是一家酒店的员工,你需要帮助这家酒店的旅客运送行李离开酒店。现在,你送顶层开始往下移动,为了减少电梯移动的距离,…

    数据结构和算法 2023年6月8日
    095
  • elasticsearch(lucene)索引数据过程

    倒排索引存储-分段存储(lucene的功能)在lucene中:lucene index包含了若干个segment在elasticsearch中:index包含了若干主从shard,…

    数据结构和算法 2023年6月7日
    082
  • Using New and Delete to manage memory directly (new header)

    1.Initialization with parentheses and curly braces. int *pi = new int(1024); string *ps = …

    数据结构和算法 2023年6月7日
    085
  • java spi实现案例

    简介 SPI(Service Provider Interface),是JDK内置的一种 服务提供发现机制,可以用来扩展和替换组件,主要是被框架的开发人员使用。 核心代码 spi接…

    数据结构和算法 2023年6月8日
    088
  • epoll服务器反应堆模型

    常规的epoll处理epoll是io多路复用的一种实现方式,最开始我们使用epoll是对多个fd进行管理,当epoll_wait从内核的rdllist就绪链表中取出一定数量的pol…

    数据结构和算法 2023年6月16日
    097
  • Python技法:用argparse模块解析命令行选项

    1. 用argparse模块解析命令行选项 我们在上一篇博客《Linux:可执行程序的Shell传参格式规范》中介绍了Linux系统Shell命令行下可执行程序应该遵守的传参规范(…

    数据结构和算法 2023年6月16日
    0112
  • linux多路转接epoll—服务器代码

    一、epoll多路转接简介 1、什么是多路转接:举个例子—如果有很多人要联系老板,需要先联系秘书,然后每隔一段时间,秘书就告知老板这段时间内有多少人联系了他,以及这些联…

    数据结构和算法 2023年6月8日
    089
  • 机器学习—神经网络

    BP神经网络的综述 1.1神经网络的定义 神经网络(neural network) 是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能够模拟生物神经系统对真实世界物体所做…

    数据结构和算法 2023年6月8日
    0126
  • 前端 Git-Hooks 工程化实践

    前言 前段时间,部门的前端项目迁移到 monorepo 架构,笔者在其中负责跟 git 工作流相关的事情,其中就包括 git hooks 相关的工程化的实践。用到了一些常用的相关工…

    数据结构和算法 2023年6月12日
    083
  • [pyplot]在同一画面上绘制不同大小的多个图像

    一、背景 做计算机应用数学作业时要求使用matplotlib库在同一张图上绘制两个图像,但是这两个图像的大小不同,百度之后发现大部分只是转载的同一篇博客,而且只能实现部分子图比例排…

    数据结构和算法 2023年6月7日
    083
  • Java多线程(1)

    我回来了,兄弟们,以后稳定每日一更哈。废话不多说,直接上码。 1 class MyThread extends Thread { 2 private String who; 3 p…

    数据结构和算法 2023年6月7日
    056
  • 类加载过程

    类加载过程本质上就是类加载器根据类的全限定名称去找到对应的class字节码文件内容,然后将字节码文件的内容加载到虚拟机方法区中的过程。所以我们大体上可以把类加载的过程分为三部分:1…

    数据结构和算法 2023年6月8日
    0100
  • 排序算法-冒泡排序

    冒泡排序 基本介绍 冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐…

    数据结构和算法 2023年6月12日
    092
  • 一个Golang的REPL工具

    REPL为Read-Eval-Print Loop的简写,为一种简易的,可交互式的编程环境,使用者可以方便的调试相关代码: Read: 读取用户输入;Eval: 计算输入的数据;P…

    数据结构和算法 2023年6月7日
    089
  • 区间dp

    一.什么是区间dp? 顾名思义:区间dp就是在区间上进行动态规划,求解一段区间上的最优解。主要是通过合并小区间的 最优解进而得出整个大区间上最优解的dp算法。 二.核心思路 既然让…

    数据结构和算法 2023年6月7日
    071
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球