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

C++ 中基类和派生类对象的赋值与转换

在 C++ 的继承关系中,基类(Base)和派生类(Derived)对象之间的赋值与转换是常见问题。理解这些规则不仅能避免常见的陷阱,还能帮助我们写出更安全的面向对象代码。本文将逐步介绍几种典型场景。


1. 基类与派生类对象的赋值

class Person
{
protected:std::string _name; std::string _sex;  int _age;          
};class Student : public Person
{
public:int _No; // 学号
};void Test()
{Student sobj;Person pobj = sobj; // ✅ 子类对象可以赋值给基类对象
}

这里发生了 切片(object slicing)

  • sobj 的基类部分被复制给 pobj

  • pobj 中只保留了 Person 的那部分数据;

  • Student 的扩展部分(如 _No)被“切掉”了。

👉 注意:基类对象无法保存派生类的完整信息。


2. 基类和派生类的指针/引用转换

(1)子类 → 父类

Student sobj;
Person* pp = &sobj;   // ✅ 合法
Person& rp = sobj;    // ✅ 合法

这是 向上转型(upcasting),始终安全,因为派生类一定包含完整的基类子对象。


(2)父类 → 子类

Person pobj;
Person* pp = &pobj;Student* ps = (Student*)pp; // ⚠️ 危险:强制类型转换
ps->_No = 10;               // ❌ 未定义行为

虽然编译器允许你写 (Student*)pp,但运行时 pp 指向的其实是一个 Person 对象,根本没有 _No 成员。这样会导致 非法内存访问,属于未定义行为。


3. 为什么有的情况能转,有的情况不能?

来看两个对比:

Student sobj;
Person pobj;Person* pp = &sobj;
Student* ps1 = (Student*)pp; // ✅ 安全,因为 pp 本来就指向 Student
ps1->_No = 10;pp = &pobj;
Student* ps2 = (Student*)pp; // ⚠️ 危险,因为 pp 指向的是 Person
ps2->_No = 10;               // ❌ 越界访问

区别在于 指针的动态类型

  • pp = &sobj;pp 指向的确实是一个 Student,强转后访问合法;

  • pp = &pobj;pp 指向的只是 Person,强转后访问不存在的内存,出错。

👉 结论:强制转换不会检查真实类型,只是告诉编译器“相信我”。


4. 更安全的做法:dynamic_cast

如果需要从基类指针“安全”地转回派生类指针,应使用 dynamic_cast

Person* pp = new Student;Student* ps = dynamic_cast<Student*>(pp);
if (ps) {ps->_No = 100;  // ✅ 转换成功
}Person* pp2 = new Person;
Student* ps2 = dynamic_cast<Student*>(pp2);
if (ps2 == nullptr) {std::cout << "转换失败,pp2 不是 Student!" << std::endl;
}

前提:基类中必须有至少一个虚函数(支持 RTTI 运行时类型识别)。


5. 总结

  1. 对象赋值:子类对象赋值给基类对象会发生切片,子类特有部分丢失。

  2. 向上转型(子类 → 基类):始终安全。

  3. 向下转型(基类 → 子类):必须小心,强制转换不安全,只有当指针真实指向派生类对象时才有效。

  4. 使用 dynamic_cast 能在运行时检查类型,避免未定义行为


文章转载自:

http://ZHOlke6Z.hwfpp.cn
http://zCRZCLZg.hwfpp.cn
http://kCrUU7Dq.hwfpp.cn
http://qXU4c17N.hwfpp.cn
http://VGu5p1b1.hwfpp.cn
http://knAkg1kt.hwfpp.cn
http://m1VGSA2z.hwfpp.cn
http://Y0cpN1Pe.hwfpp.cn
http://OOVqWNik.hwfpp.cn
http://xoNZgruu.hwfpp.cn
http://24man9nL.hwfpp.cn
http://6tYjmLdg.hwfpp.cn
http://jjKCHocy.hwfpp.cn
http://TxUbSBcq.hwfpp.cn
http://d1cmCfpS.hwfpp.cn
http://BrLz77vi.hwfpp.cn
http://dGK5P6Vy.hwfpp.cn
http://WJBM6tDg.hwfpp.cn
http://ppH8oyhF.hwfpp.cn
http://18pjWs6t.hwfpp.cn
http://cRBxun7h.hwfpp.cn
http://zQr589f7.hwfpp.cn
http://cLcfCReO.hwfpp.cn
http://3yfKF9gd.hwfpp.cn
http://STH1pO8i.hwfpp.cn
http://rAHJrdcc.hwfpp.cn
http://hiHhOzQp.hwfpp.cn
http://6spqyZsy.hwfpp.cn
http://5xTd8jH1.hwfpp.cn
http://iDCed0RI.hwfpp.cn
http://www.dtcms.com/a/367405.html

相关文章:

  • STM32F103_Bootloader程序开发15 - 从Keil到vscode + EIDE + GCC的迁移实践
  • 神马 M21 31T 矿机解析:性能、规格与市场应用
  • 解析 Quartz 报错:Table ‘test.QRTZ_LOCKS‘ doesn‘t exist 的解决方案
  • 【高等数学】第十一章 曲线积分与曲面积分——第二节 对坐标的曲线积分
  • 产品推荐|千眼狼宽光谱高速摄像机NEO系列
  • ECIES实现原理
  • Linux安装RTL8821CE无线网卡驱动
  • 下载及交叉编译libconfig
  • AutoLayout与Masonry:简化iOS布局
  • 《计算机网络安全》实验报告一 现代网络安全挑战 拒绝服务与分布式拒绝服务攻击的演变与防御策略(2)
  • upload-labs通关笔记-第17关文件上传关卡之二次渲染jpg格式
  • 人工智能机器学习——逻辑回归
  • Java Web 是技术与产业的 “交叉赋能点”
  • Linux笔记---UDP套接字实战:简易聊天室
  • 新增MCP工具管理,AI对话节点新增工具设置,支持对接企业微信机器人,MaxKB v2.1.0版本发布
  • 2025年数学建模国赛C题超详细解题思路
  • 【论文阅读】-《Besting the Black-Box: Barrier Zones for Adversarial Example Defense》
  • 小迪web自用笔记27
  • 不会战略、不会融资、不会搭团队?别叫自己 CTO
  • ⸢ 肆 ⸥ ⤳ 默认安全建设方案:b.安全资产建设
  • 【高分论文密码】大尺度空间模拟预测与数字制图
  • 机器翻译:腾讯混元团队开源的模型 Hunyuan-MT 详解
  • #数据结构----2.1线性表
  • IT需求提示未读信息查询:深度技术解析与性能优化指南【类似:钉钉已读 功能】
  • RAG(检索增强生成)-篇一
  • 解密注意力机制:为何它能在Transformer中实现高效并行计算?
  • 2025跨境独立站最新最完整的搭建流程
  • 2025年百度商业AI技术创新大赛赛道二:视频广告生成推理性能优化-初赛第五名,复赛第九名方案分享
  • VS code如何下载安装
  • 跨部门共享研发文档总是困难重重该如何改善