C++ 继承与多态完全详解
面向对象三大特性封装、继承、多态。如果说封装让代码更安全那么继承让代码复用多态让代码可扩展。继承和多态是 C 面向对象的重中之重、面试必考、工程必用。很多同学学完只会背概念分不清重写、重载、隐藏不懂虚函数原理不知道动态绑定到底是什么。本文带你从零吃透继承体系 访问权限 构造析构规则 多态原理 虚函数 纯虚函数 抽象类全程配图、流程图、可运行代码一次性搞定所有难点。一、什么是继承核心概念1.1 生活理解继承子类拥有父类的所有属性和行为并且可以扩展自己的新功能。父类基类通用、抽象、公共代码子类派生类特有、扩展、个性化代码1.2 继承的作用代码复用公共代码只写一次所有子类直接复用代码分层结构清晰层级明确为多态做铺垫没有继承就没有多态1.3 继承语法class 子类名 : 继承方式 父类名 { // 子类新成员 };1.4 三种继承方式面试重点C 支持三种继承public / protected / private继承方式父类 public父类 protected父类 private使用场景public 公有继承publicprotected不可见日常开发 99% 使用protected 保护继承protectedprotected不可见极少用private 私有继承privateprivate不可见几乎不用核心结论private 成员永远无法被子类继承访问想让父类成员子类能用、外部不能用→ 用protected工程开发只记一律使用 public 继承二、继承中的构造与析构顺序2.1 核心规则构造函数先父后子析构函数先子后父2.2 执行流程可视化2.3 验证代码#include iostream using namespace std; class Parent { public: Parent() { cout 父类构造 endl; } ~Parent() { cout 父类析构 endl; } }; class Child : public Parent { public: Child() { cout 子类构造 endl; } ~Child() { cout 子类析构 endl; } }; int main() { Child c; return 0; }输出顺序父类构造 → 子类构造 → 子类析构 → 父类析构三、继承中的同名隐藏踩坑重点3.1 什么是隐藏当子类和父类有同名成员函数/变量子类函数会隐藏父类同名函数父类函数在子类中不可见。3.2 隐藏 vs 重写提前区分隐藏普通函数父子同名不构成多态重写覆盖虚函数父子同名同参构成多态四、多态详解OOP 灵魂4.1 什么是多态多态同一行为不同表现。通俗理解父类指针指向子类对象调用函数时执行子类的方法。4.2 多态的成立条件面试必考四条必须同时满足存在继承关系父类有virtual 虚函数子类重写override虚函数父类指针/引用 指向子类对象4.3 多态执行原理流程图4.4 多态完整实战代码#include iostream using namespace std; // 父类 class Animal { public: // 虚函数支持多态 virtual void speak() { cout 动物在叫 endl; } }; // 子类1 class Dog : public Animal { public: // 重写虚函数 void speak() override { cout 汪汪汪 endl; } }; // 子类2 class Cat : public Animal { public: void speak() override { cout 喵喵喵 endl; } }; // 统一接口实现多态 void doSpeak(Animal a) { a.speak(); } int main() { Dog d; Cat c; doSpeak(d); doSpeak(c); return 0; }输出结果汪汪汪 、 喵喵喵关键点同样的speak()接口不同对象不同行为这就是多态。五、重载、重写、隐藏 终极区别面试高频类型作用域函数签名virtual是否多态重载 Overload同类函数名同参数不同不需要否隐藏 Hide父子类同名即可非虚函数否重写 Override父子类完全一致名/参/返回必须 virtual是六、虚函数、纯虚函数、抽象类6.1 普通虚函数有默认实现子类可重写也可不重写。virtual void func() {}6.2 纯虚函数重点没有实现强制子类必须重写。virtual void func() 0;6.3 抽象类包含纯虚函数的类就是抽象类。特性无法实例化对象只能被继承子类必须实现所有纯虚函数否则子类也是抽象类6.4 抽象类实战接口思想#include iostream using namespace std; // 抽象父类 class Shape { public: // 纯虚函数 virtual void getArea() 0; }; class Circle : public Shape { public: void getArea() override { cout 圆形面积 endl; } }; class Rect : public Shape { public: void getArea() override { cout 矩形面积 endl; } }; int main() { Shape *s1 new Circle(); Shape *s2 new Rect(); s1-getArea(); s2-getArea(); delete s1; delete s2; return 0; }七、多态底层原理虚函数表 vtable7.1 什么是虚表一旦类中出现virtual函数编译器会自动生成一张虚函数表。每个对象内存中会多出一个虚表指针 vptr指向本类的虚表。7.2 多态调用原理父类指针指向子类对象通过对象的 vptr 找到虚表调用虚表中子类重写后的函数地址这就是动态绑定运行时确定调用哪个函数7.3 静态绑定 vs 动态绑定普通函数静态绑定编译阶段确定调用地址虚函数动态绑定运行时根据对象真实类型确定八、继承多态经典坑点虚析构函数8.1 问题场景父类指针 delete 子类对象时如果析构非虚只会调用父类析构子类内存泄漏8.2 正确写法class Parent { public: virtual ~Parent() {} // 虚析构 };工程规范只要类可能被继承析构函数一律写 virtual九、全文总结1. 继承核心目的代码复用、层级抽象构造先父后子析构先子后父开发只用public 继承2. 多态核心条件继承 虚函数 重写 父指子对象本质动态绑定、虚函数表价值接口统一、扩展性极强开闭原则3. 三大函数区别重载同域、参数不同隐藏父子同名、非虚函数重写父子虚函数、完全覆盖 ——唯一多态4. 工程准则需要复用 → 继承需要统一接口、多场景扩展 → 多态 虚函数基类析构必写 virtual统一规范用 override 显式重写
