IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++中static_cast和dynamic_cast强制类型转换 -> 正文阅读

[C++知识库]C++中static_cast和dynamic_cast强制类型转换

1.static_cast关键字(编译时类型检查)

用法:

  • static_cast < type-id > ( expression ),该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性

它主要有如下几种用法:

  • (1)用于基本数据类型之间的转换,如把int转换为char,把int转换成enum,但这种转换的安全性需要开发者自己保证(这可以理解为保证数据的精度,即程序员能不能保证自己想要的程序安全),如在把int转换为char时,如果char没有足够的比特位来存放int的值(int>127或int<-127时),那么static_cast所做的只是简单的截断,及简单地把int的低8位复制到char的8位中,并直接抛弃高位。
  • (2)把空指针转换成目标类型的空指针
  • (3)把任何类型的表达式类型转换成void类型
  • (4)用于类层次结构中父类和子类之间指针和引用的转换。

对于static_cast,上行转换时安全的,而下行转换时不安全的
因为static_cast的转换时粗暴的,它仅根据类型转换语句中提供的信息(尖括号中的类型)来进行转换,这种转换方式对于上行转换,由于子类总是包含父类的所有数据成员和函数成员,因此从子类转换到父类的指针对象可以没有任何顾虑的访问其(指父类)的成员。
而对于下行转换为什么不安全,是因为static_cast只是在编译时进行类型检查,没有运行时的类型检查,具体原理在dynamic_cast中说明。

2.dynamic_cast关键字(运行时类型检查)

用法:

【格式】dynamic_cast<type_id>(expression) :

该运算符把expression转换为type_id 类型, type_id 可以为类的指针、类的引用、void*,expression为对应的指针或引用.
  • dynamic_cast是四个强制类型转换操作符中最特殊的一个,它支持运行时识别指针或引用。
  • 首先,dynamic_cast依赖于RTTI信息,其次,在转换时,dynamic_cast会检查转换的source对象是否真的可以转换成target类型,
    这种检查不是语法上的,而是真实情况的检查。
  • 若对指针进行dynamic_cast,失败返回nullptr,成功返回正常cast后的对象指针;
  • 若对引用进行dynamic_cast,失败抛出一个异常,成功返回正常cast后的对象引用

dynamic_cast,主要用于类层次间的转换:

  • 上行转换(子类转父类),转换安全,成功返回类对象指针, 此时和static_cast 作用一样。

  • 下行转换(父类转子类), 父类中要有虚函数,否则编译器报错。转换分几种情况:
    a. 父类指针指向子类对象,转换安全, dynamic_cast返回类对象指针。
    b.父类指针指向父类对象,转换不安全,dynamic_cast 返回nullptr。
    此时若使用static_cast, 返回非空指针,更不安全。

  • eg:

#include <iostream>

using namespace std;

class A{
public:
    A(){}
    virtual void eat()
    {
        std::cout<<"A::eat()"<<std::endl;
    }

    void sing(){
        std::cout<<"A::sing()"<<std::endl;
    }
    ~A(){};
};

class B : public A{
public:
    B() {};
    void eat()
    {
        std::cout<<"B::eat()"<<std::endl;
    }
    void sing()
    {
        std::cout<<"B::sing()"<<std::endl;
    }
    ~B(){}
    int data;
};


int main()
{
    A* a= nullptr;
    B* b = nullptr;

    A aa;
    B bb;
    b = &bb;
    // 安全的向上转型
    a = dynamic_cast<A*>(b);
    a->sing();
    a->eat();
    std::cout<<"===="<<std::endl;
    // 向下转型,向下转型时,父类必须含有虚函数,否则编译报错
    //父类指针指向子类对象,这样的dynamic_cast向下转换才是安全的
    a = &bb;
    b = dynamic_cast<B*>(a);
    
    b->sing();//yes
    b->eat();//yes
    std::cout<<"===="<<std::endl;
    //父类指针指向父类对象,这样的dynamic_cast向下转换是不安全的
    a = &aa;
    b = dynamic_cast<B*>(a);
    if (b == nullptr)
    {
        std::cout<<"the call is not safe "<<std::endl;
    }
    b->sing();//yes
    b->eat();//Segmentation fault
    std::cout<<"===="<<std::endl;
    
    //static_cast不做类型检查,不返回nullptr,不安全
    b = static_cast<B*>(a);
    if (b == nullptr)
    {
        std::cout<<"second the call is not safe "<<std::endl;
    }

    b->sing();//yes
    b->eat();//居然调用的基类的eat,不对

    return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 10:25:04  更:2022-08-06 10:29:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年3日历 -2024/3/29 19:51:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码