当前位置: 首页 > news >正文

【C++】类型转换 ④ ( 子类 和 父类 之间的类型转换 - 动态类型转换 dynamic_cast )

文章目录

  • 一、子类 和 父类 之间的类型转换 - 动态类型转换 dynamic_cast
    • 1、构造父类和子类
    • 2、子类 和 父类 之间的类型转换 - 隐式类型转换
    • 3、子类 和 父类 之间的类型转换 - 静态类型转换 static_cast
    • 4、子类 和 父类 之间的类型转换 - 重新解释类型转换 reinterpret_cast
    • 5、子类 和 父类 之间的类型转换 - 动态类型转换 dynamic_cast
  • 二、完整代码示例
    • 1、代码示例
    • 2、执行结果


在之前写过一篇 C++ 类型转换的博客 【C++ 语言】类型转换 ( 转换操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast | 字符串转换 ) , 简单介绍了 C++ 类型转换 ;

在 博客 【C++】类型转换 ① ( C 中的类型转换 | C++ 类型转换操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast ) 将 C 语言 和 C++ 中的类型转换进行了对比 ;

在 博客 【C++】类型转换 ② ( C++ 静态类型转换 static_cast | C 语言隐式转换弊端 | 代码示例 ) 中 , 主要分析了 静态类型转换 static_cast , 可以解决 C 语言隐式转换的弊端 ;

在博客 【C++】类型转换 ③ ( 重新解释类型转换 reinterpret_cast | 指针类型数据转换 ) 分析了 指针数据类型的转换 , 在 C 语言环境下 , 可以使用显示强制类型转换 , 在 C++ 环境中只能使用 重新解释类型转换 reinterpret_cast ;


本篇博客中 , 分析 C++ 环境下 使用 各种方式 进行 父类 和 子类 类型之间的转换 , 推荐使用 动态类型转换 dynamic_cast ;





一、子类 和 父类 之间的类型转换 - 动态类型转换 dynamic_cast



C++ 面向对象 应用场景中 , 涉及到 父类 和 子类 之间的转换 ;

很明显 C 语言的 强制类型转换 , 不管是 隐式 还是 显示 转换 , 都无法转换 C++ 对象的类型 ;

动态类型转换 dynamic_cast 一般用于 父类 ( 对象 / 指针 / 引用 ) 和 子类 ( 对象 / 指针 / 引用 ) 之间的转换 , 是 C++ 语言特有的 , C 语言中没有该转换类型 ;


1、构造父类和子类


编写一个 父类 , 其中定义一个纯虚函数 ;

再编写两个 子类 , 重写 父类的 纯虚函数 , 每个子类再 各自定义一个 特有的函数 ;

// 父类
class Father
{
public:virtual void say() = 0;
};// 子类
class Son : public Father
{
public:void say(){cout << "Son" << endl;}// Son 子类的特有函数void son_say(){cout << "son_say" << endl;}
};// 子类2
class Son2 : public Father
{
public:void say(){cout << "Son2" << endl;}// Son2 子类的特有函数void son2_say(){cout << "son2_say" << endl;}
};

2、子类 和 父类 之间的类型转换 - 隐式类型转换


先创建 子类对象 ,

将子类对象的 地址赋值给 父类指针 , 其中包含了 隐式转换 ;

在下面的代码中 , 使用取地址符获取 Son 类型 子类对象的地址 , 指针类型是 Son* 类型 , 将该类型值 赋值给 Father* 指针 , 其中进行了 隐式类型转换 ;

	Son son;// 创建父类指针 , 直接让父类指针指向子类对象// 不会报错 , 但是这么做有一定的风险Father* pFather = NULL;// 隐式类型转换pFather = &son;

此外 , 函数接收 父类指针形参 作为参数 , 如果调用该函数 , 传入子类指针 , 此时涉及到将 子类指针 Son* 隐式转为 父类指针 Father* ;

// 函数接收 父类对象 作为参数, 可传入子类对象
void objSay(Father* obj)
{
}// 调用函数, 传入子类对象指针
objSay(&son);

3、子类 和 父类 之间的类型转换 - 静态类型转换 static_cast


静态类型转换 static_cast , 可以在 C++ 编译器 编译时 对类型转换 进行检查 ;

如果 转换的类型不匹配 , 就会在编译时报错 , 避免出现更大的错误 ;


下面的代码中 , 使用取地址运算符 &son 获取 的 Son* 类型的 指针 , 将其使用 静态类型转换 static_cast 转为 Father* 类型的指针 ,

在 C++ 编译器编译阶段 , 会对类型进行检测 , 如果通过检测 , 则可以编译成功 , 如果类型错误 , 则会出现编译时报错的情况 ;

	Son son;// 创建父类指针 , 直接让父类指针指向子类对象// 不会报错 , 但是这么做有一定的风险Father* pFather = NULL;// 静态类型转换 static_cast,  可以在编译时 对类型转换 进行检查pFather = static_cast<Father*>(&son);

下面的代码就是 执行静态类型转换 检查出错的情况 ,

Son 和 Son2 都是 Father 的子类 , 二者之间不能相互转化 , 只能是 父类 和 子类 之间进行相互转换 ;

类型转换错误报错 : error C2440: “static_cast”: 无法从“Son *”转换为“Son2 *” ;

	Son son;Son2 son2;// 创建父类指针 , 直接让父类指针指向子类对象// 不会报错 , 但是这么做有一定的风险Father* pFather = NULL;// 静态类型转换 static_cast,  可以在编译时 对类型转换 进行检查pFather = static_cast<Father*>(&son);// 类型转换错误报错 : error C2440: “static_cast”: 无法从“Son *”转换为“Son2 *”// message : 与指向的类型无关;//		强制转换要求 reinterpret_cast、C 样式强制转换或函数样式强制转换Son2* pSon2 = static_cast<Son2*>(&son);

执行后 , 出现如下报错 :

已启动生成…
1>------ 已启动生成: 项目: HelloWorld, 配置: Debug Win32 ------
1>Test.cpp
1>D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\Test.cpp(92,39): error C2440:static_cast: 无法从“Son *”转换为“Son2 *1>D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\Test.cpp(92,16): message : 与指向的类型无关;强制转换要求 reinterpret_cast、C 样式强制转换或函数样式强制转换
1>已完成生成项目“HelloWorld.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0==========

完整代码示例 :

#include "iostream"
using namespace std;// 父类
class Father
{
public:virtual void say() = 0;
};// 子类
class Son : public Father
{
public:void say(){cout << "Son" << endl;}// Son 子类的特有函数void son_say(){cout << "son_say" << endl;}
};// 子类2
class Son2 : public Father
{
public:void say(){cout << "Son2" << endl;}// Son2 子类的特有函数void son2_say(){cout << "son2_say" << endl;}
};// 函数接收 父类对象 作为参数, 可传入子类对象
void objSay(Father* obj)
{// 调用 父类 纯虚函数 可发生多态调用// 传入不同的子类 调用的是不同的函数obj->say();
}int main() {Son son;Son2 son2;// 创建父类指针 , 直接让父类指针指向子类对象// 不会报错 , 但是这么做有一定的风险Father* pFather = NULL;// 静态类型转换 static_cast,  可以在编译时 对类型转换 进行检查pFather = static_cast<Father*>(&son);// 类型转换错误报错 : error C2440: “static_cast”: 无法从“Son *”转换为“Son2 *”// message : 与指向的类型无关;//		强制转换要求 reinterpret_cast、C 样式强制转换或函数样式强制转换Son2* pSon2 = static_cast<Son2*>(&son);// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
};

执行结果 :

已启动生成…
1>------ 已启动生成: 项目: HelloWorld, 配置: Debug Win32 ------
1>Test.cpp
1>D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\Test.cpp(92,39): error C2440:static_cast: 无法从“Son *”转换为“Son2 *1>D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\Test.cpp(92,16): message : 与指向的类型无关;强制转换要求 reinterpret_cast、C 样式强制转换或函数样式强制转换
1>已完成生成项目“HelloWorld.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0==========

在这里插入图片描述


4、子类 和 父类 之间的类型转换 - 重新解释类型转换 reinterpret_cast


C++ 中 父类 和 子类 之间类型转换 , 还可以使用 重新解释类型转换 reinterpret_cast ;

下面的代码中 , 将 Son* 指针类型 重新解释为 Father* 指针类型 ;

	// C++ 强制类型转换 , 重新解释类型转换 reinterpret_castpFather = reinterpret_cast<Father*>(&son);pFather->say();

5、子类 和 父类 之间的类型转换 - 动态类型转换 dynamic_cast


动态类型转换 dynamic_cast , 一般用于 子类 和 父类 之间的类型转换 ,

  • 运行时 , 如果类型转换成功 , 则进行转换 ;
  • 运行时 , 如果类型转换失败 , 则返回转换结果 NULL ;

借助上述特性 , 动态类型转换 dynamic_cast 可用于在 运行时 识别对象类型 ;

将 对象 强转为 指定类型对象, 如果失败了, 转换结果为 NULL , 说明被转换的对象 不是 指定类型的对象 ;


下面代码的作用是 : 将Father* obj 父类对象 强转为 Son* 子类对象 ,

  • 如果转换成功, 说明 obj 对象就是 Son 子类对象 , 则执行 Son 子类对象特有的函数 ;
  • 如果转换失败, 说明不是 Son 子类对象, 转换结果是 NULL , 也就是 0 , 后续不再处理 ;
	// 将Father* obj 父类对象 强转为 Son* 子类对象// 如果转换成功, 说明 obj 对象就是 Son 子类对象// 如果转换失败, 说明不是 Son 子类对象, 转换结果是 NULL , 也就是 0Son* son = dynamic_cast<Son*>(obj);if (son != NULL){// 转换成功// 执行 Son 特有工作son->son_say();}

完整代码 , 参考下面章节的 完整代码示例 ;





二、完整代码示例




1、代码示例


#include "iostream"
using namespace std;// 父类
class Father
{
public:virtual void say() = 0;
};// 子类
class Son : public Father
{
public:void say(){cout << "Son" << endl;}// Son 子类的特有函数void son_say(){cout << "son_say" << endl;}
};// 子类2
class Son2 : public Father
{
public:void say(){cout << "Son2" << endl;}// Son2 子类的特有函数void son2_say(){cout << "son2_say" << endl;}
};// 函数接收 父类对象 作为参数, 可传入子类对象
void objSay(Father* obj)
{// 调用 父类 纯虚函数 可发生多态调用// 传入不同的子类 调用的是不同的函数obj->say();// 动态类型转换 dynamic_cast// 可用于在 运行时 识别对象类型// 将 对象 强转为 指定类型对象, 如果失败了, 转换结果为 NULL// 将Father* obj 父类对象 强转为 Son* 子类对象// 如果转换成功, 说明 obj 对象就是 Son 子类对象// 如果转换失败, 说明不是 Son 子类对象, 转换结果是 NULL , 也就是 0Son* son = dynamic_cast<Son*>(obj);if (son != NULL){// 转换成功// 执行 Son 特有工作son->son_say();}// 将Father* obj 父类对象 强转为 Son2* 子类对象// 如果转换成功, 说明 obj 对象就是 Son2 子类对象// 如果转换失败, 说明不是 Son2 子类对象, 转换结果是 NULL , 也就是 0Son2* son2 = dynamic_cast<Son2*>(obj);if (son2 != NULL){// 转换成功// 执行 Son2 特有工作son2->son2_say();}
}int main() {Son son;Son2 son2;// 创建父类指针 , 直接让父类指针指向子类对象// 不会报错 , 但是这么做有一定的风险Father* pFather = NULL;// 静态类型转换 static_cast,  可以在编译时 对类型转换 进行检查pFather = static_cast<Father*>(&son);// 类型转换错误报错 : error C2440: “static_cast”: 无法从“Son *”转换为“Son2 *”// message : 与指向的类型无关;//		强制转换要求 reinterpret_cast、C 样式强制转换或函数样式强制转换//Son2* pSon2 = static_cast<Son2*>(&son);// C++ 强制类型转换 , 重新解释类型转换 reinterpret_castpFather = reinterpret_cast<Father*>(&son);pFather->say();// 动态类型转换示例objSay(&son);objSay(&son2);// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
};

2、执行结果


执行结果 :

Son
Son
son_say
Son2
son2_say
Press any key to continue . . .

在这里插入图片描述

http://www.lryc.cn/news/246273.html

相关文章:

  • 在CentOS 7.9上搭建高性能的FastDFS+Nginx文件服务器集群并实现外部远程访问
  • YOLOv8独家原创改进: AKConv(可改变核卷积),即插即用的卷积,效果秒杀DSConv | 2023年11月最新发表
  • Docker pause/unpause命令
  • PostgreSQL create or replace view和重建视图 有什么区别?
  • Selenium 连接到现有的 Firefox 示例
  • 小程序如何进行版本回退
  • 15:00面试,15:06就出来了,问的问题有点变态。。。
  • 大数据-之LibrA数据库系统告警处理(ALM-37008 MPPDB服务不可用)
  • Pytorch-gpu环境篇
  • 互联网上门洗鞋店小程序
  • 【深度学习笔记】04 概率论基础
  • 45.113.200.1搜索引擎蜘蛛抓取不到网站内容页面可能的原因
  • VMware 系列:vSphere Client安装配置常见问题及解决方案
  • FLASK博客系列5——模板之从天而降
  • 6.一维数组——用冒泡法将10个整数由大到小排序
  • Wireshark的捕获过滤器
  • 安陆FPGA调试中遇到的问题总结
  • Springboot2+WebSocket
  • 希尔伯特和包络变换
  • 国产Ai大模型和chtgpt3.5的比较
  • 机器学习ROC曲线中的阈值thresholds
  • MySOL常见四种连接查询
  • 数智融合 开启金融数据治理新时代
  • 数据结构——利用堆进行对数组的排序
  • Unity 场景切换
  • 【PTA题目】7-12 N个数求和 分数 20
  • 智能AIGC写作系统ChatGPT系统源码+Midjourney绘画+支持GPT-4-Turbo模型+支持GPT-4图片对话
  • List转string 逗号分隔
  • 手机文件怎么传到电脑?简单方法分享!
  • 计算机基础知识59