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. 抽象类包含纯虚函数,不能实例对象,强制子类实现接口。

相关推荐
倒头就睡的小比特16 小时前
算法竞赛C++常用的STL
c++·算法
weilx123416 小时前
C++笔记-文件IO-<fcntl.h>
c++
小羊没烦恼!16 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读17 小时前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
Smileyqp沛沛17 小时前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车18 小时前
C/C++ 为什么需要编译器?
开发语言·c++
旖旎夜光18 小时前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
吞下星星的少年·-·19 小时前
C++ 萌新语法入门篇
c++·算法比赛
霍霍的袁19 小时前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
another heaven19 小时前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法