C++继承与多态核心笔记|菱形继承、组合、虚函数、纯虚函数一网打尽

一、继承模型

1. 单继承

一个派生类只有一个直接基类,就是单继承。

2. 多继承

一个派生类有两个及以上直接基类,就是多继承。 内存布局:先继承的基类在前面,后继承的基类在后面,派生类自身成员放在最后。

3. 菱形继承(钻石继承)

菱形继承是多继承的特殊情况。

  • 问题 :普通多继承会造成数据冗余、二义性,公共基类成员存多份。

  • 解决:虚继承 virtual:虚继承之后公共基类只保留一份。

Java 直接不支持多继承,直接规避菱形继承问题,工程实践尽量避免设计菱形继承。

二、多继承指针偏移问题

复制代码
class Base1 { public: int _b1; };
class Base2 { public: int _b2; };
class Derive : public Base1, public Base2 { public: int _d; };

int main()
{
    Derive d;
    Base1* p1 = &d;
    Base2* p2 = &d;
    Derive* p3 = &d;
    return 0;
}
  • p1指向对象起始地址,对应Base1子对象;

  • p2指向Base2子对象,指针会向后偏移

  • p3指向完整派生类对象起始地址。

所以 p1 != p2,p1 == p3。多继承向上转型,不同基类指针地址不一定相等。

三、继承和组合

本质:都是复用成员。

  1. public 继承:is‑a 派生类对象本质就是一个基类对象,属于白箱复用。 子类可以访问父类保护成员,耦合度高,父类改动会强烈影响子类。

  2. 组合:has‑a 把类对象作为另一个类的成员,属于黑箱复用。 内部细节对外不可见,类之间依赖弱,耦合度低

✅工程原则:优先使用组合,而不是继承

  • is‑a 关系,用继承;

  • has‑a 关系,优先组合;

  • 需要实现多态,必须使用继承。

高内聚、低耦合是软件工程核心追求。

四、多态

1. 多态两个必要条件

  1. 基类指针 / 引用调用函数;

  2. 调用的是虚函数,派生类完成虚函数重写 (覆盖)。

2. 虚函数重写(三同)

派生类虚函数和基类虚函数,返回值、函数名、参数列表全部相同,叫重写。
小坑:派生类不加 virtual,只要满足三同,依然构成重写,语法允许,但可读性差,考试选择题高频坑点。

3. 虚析构函数

基类析构建议写为virtual虚析构。

  • 如果基类析构是虚函数,派生类析构自动构成重写,不管写不写 virtual。

  • delete 基类指针指向派生类对象,只有基类析构为虚,才会调用派生类析构,否则只会调用基类析构,派生类资源泄漏

五、重载、重写 (覆盖)、隐藏三大概念对比

  1. 重载:同一个作用域,函数名相同,参数列表不同。

  2. 重写 / 覆盖:继承体系,基类和派生类,虚函数,三同。

  3. 隐藏:派生类定义和基类同名函数,不管参数是否相同,基类同名函数直接被隐藏。

六、纯虚函数 & 抽象类

复制代码
virtual void func() = 0;
  1. 虚函数后面写=0,就是纯虚函数,可以不写函数体。

  2. 拥有纯虚函数的类叫抽象类

  3. 抽象类不能实例化对象

  4. 派生类必须重写全部纯虚函数,否则派生类也变成抽象类,也不能实例化。

抽象类强制约束派生类必须实现接口。


考点小结

  1. 菱形继承:普通继承造成二义性冗余,virtual虚继承解决;

  2. 多继承向上转型,不同基类指针地址会偏移,不一定相等;

  3. 优先组合,is‑a 才用继承;

  4. 多态两大条件:基类指针 / 引用 + 虚函数重写;

  5. 基类析构建议 virtual,防止派生类内存泄漏;

  6. 抽象类包含纯虚函数,不能实例对象,强制子类实现接口。

相关推荐
恋恋西风2 小时前
C++ 理解 std::thread 在单核和多核上的行为差异
开发语言·c++
Brilliantwxx2 小时前
【Linux】 进程(9)程序与进程地址空间(基础+进阶+面试题)
linux·运维·服务器·开发语言·c++
BizzZ_3 小时前
C++(22)——类型转换和IO流
开发语言·c++
小范同学_3 小时前
JDK1.7 与 JDK1.8 HashMap 底层原理对比 + 数组并发扩容死循环详解
java·开发语言
geovindu3 小时前
CSharp: 万年历
开发语言·后端·c#·.net
我找到地球的支点啦4 小时前
Matlab系列(009) 一CRC循环冗余校验详解
开发语言·数据结构·算法·matlab·信息与通信
予昊4 小时前
从零实现“在线五子棋对战“:WebSocket 实时通信 + 段位匹配
java·开发语言·网络·websocket
weixin_461408584 小时前
Mybatis-flex小记
java·开发语言·mybatis
青梅味猪大肠6 小时前
【深入浅出C++】为什么虚表指针可以解决菱形继承
开发语言·c++
潘潘的嵌入式日记6 小时前
I²C 从机接收总被覆盖?双缓冲要在 STOP 时交接
c语言·开发语言·单片机