C++ 继承:面向对象的代码复用核心机制

C++ 继承:面向对象的代码复用核心机制

C++ 继承:面向对象的代码复用核心机制

在这里插入图片描述

💡 学习目标:掌握继承的基本语法与核心特性,理解不同继承方式的访问权限控制,能够通过继承实现代码复用与扩展。
💡 学习重点:继承的语法格式、三种继承方式的区别、基类与派生类的关系、继承中的构造与析构顺序。

一、继承的概念与核心价值

结论:继承是 C++ 面向对象三大特性之一,允许一个类派生类继承另一个类基类的属性和行为,实现代码复用,同时支持派生类在基类基础上扩展新功能。

继承的核心价值体现在两个方面:

  1. 代码复用:避免重复编写相同的成员变量和成员函数,降低代码冗余度
  2. 功能扩展:派生类可以在基类的基础上新增属性和方法,满足更复杂的业务需求

生活中的继承示例:学生和老师都属于“人”,都有姓名、年龄等属性和吃饭、睡觉等行为。可以先定义 Person 基类,再让 StudentTeacher 继承 Person,并各自扩展专属功能。

二、继承的基本语法与实现

2.1 继承的语法格式

class 派生类名 : 继承方式 基类名 {// 派生类的成员};
  • 继承方式:决定基类成员在派生类中的访问权限,包括 publicprotectedprivate 三种
  • 基类名:被继承的类,也叫父类或超类
  • 派生类名:继承基类的类,也叫子类或衍生类

2.2 继承的基础实现案例

💡 以 Person 作为基类,Student 作为派生类为例,演示继承的基本用法

#include<iostream>#include<string>usingnamespace std;// 基类:人classPerson{public: string name;int age;voideat(){ cout << name <<" 正在吃饭"<< endl;}voidsleep(){ cout << name <<" 正在睡觉"<< endl;}};// 派生类:学生,公有继承 PersonclassStudent:publicPerson{public:// 派生类新增属性:学号int studentID;// 派生类新增方法:学习voidstudy(){ cout << name <<" 正在学习,学号:"<< studentID << endl;}};intmain(){// 创建派生类对象 Student s;// 访问从基类继承的属性 s.name ="张三"; s.age =18;// 访问派生类自身的属性 s.studentID =2024001;// 调用从基类继承的方法 s.eat(); s.sleep();// 调用派生类自身的方法 s.study();return0;}

2.3 运行结果

张三 正在吃饭 张三 正在睡觉 张三 正在学习,学号:2024001 

三、三种继承方式的访问权限控制

💡 继承方式直接影响基类成员在派生类中的访问权限,核心规则是继承方式不会提升成员的访问权限,只会限制或保持原有权限

3.1 三种继承方式的权限对比表

基类成员权限public 继承protected 继承private 继承
publicpublicprotectedprivate
protectedprotectedprotectedprivate
private不可访问不可访问不可访问

⚠️ 核心注意点

  1. 基类的 private 成员在派生类中始终不可直接访问,只能通过基类的 publicprotected 方法间接访问
  2. 继承方式的限制作用是单向的,派生类无法突破基类的权限限制
  3. 实际开发中,public 继承是最常用的方式,protected 和 private 继承仅在特定场景使用

3.2 不同继承方式的代码演示

3.2.1 public 继承演示
#include<iostream>#include<string>usingnamespace std;classBase{public:int pub;protected:int pro;private:int pri;};// 公有继承classPubDerived:publicBase{public:voidshow(){ pub =10;// 合法:public 继承后仍为 public pro =20;// 合法:public 继承后为 protected// pri = 30; // 非法:基类 private 成员不可访问}};intmain(){ PubDerived pd; pd.pub =100;// 合法:类外可访问 public 成员// pd.pro = 200; // 非法:protected 成员类外不可访问return0;}
3.2.2 protected 继承演示
classProDerived:protectedBase{public:voidshow(){ pub =10;// 合法:protected 继承后为 protected pro =20;// 合法:protected 继承后仍为 protected// pri = 30; // 非法:基类 private 成员不可访问}};intmain(){ ProDerived prd;// prd.pub = 100; // 非法:protected 继承后 pub 变为 protected,类外不可访问return0;}
3.2.3 private 继承演示
classPriDerived:privateBase{public:voidshow(){ pub =10;// 合法:private 继承后为 private pro =20;// 合法:private 继承后为 private// pri = 30; // 非法:基类 private 成员不可访问}};intmain(){ PriDerived prd;// prd.pub = 100; // 非法:private 继承后 pub 变为 private,类外不可访问return0;}

四、继承中的构造与析构顺序

💡 派生类对象的创建和销毁过程,会涉及基类和派生类的构造函数、析构函数调用,其顺序有严格的规则。

4.1 核心规则

构造顺序:先调用基类的构造函数,再调用派生类的构造函数
析构顺序:先调用派生类的析构函数,再调用基类的析构函数
简单记忆:构造先基后派,析构先派后基

4.2 代码演示:构造与析构顺序

#include<iostream>#include<string>usingnamespace std;classPerson{public:Person(){ cout <<"Person 基类构造函数被调用"<< endl;}~Person(){ cout <<"Person 基类析构函数被调用"<< endl;}};classStudent:publicPerson{public:Student(){ cout <<"Student 派生类构造函数被调用"<< endl;}~Student(){ cout <<"Student 派生类析构函数被调用"<< endl;}};intmain(){// 创建派生类对象 Student s;// 函数结束时对象销毁,自动调用析构函数return0;}

4.3 运行结果

Person 基类构造函数被调用 Student 派生类构造函数被调用 Student 派生类析构函数被调用 Person 基类析构函数被调用 

4.4 带参数的构造函数继承

当基类只有带参数的构造函数时,派生类必须在初始化列表中显式调用基类的构造函数。

#include<iostream>#include<string>usingnamespace std;classPerson{public: string name;int age;// 基类带参数构造函数Person(string n,int a){ name = n; age = a; cout <<"Person 带参构造函数被调用"<< endl;}};classStudent:publicPerson{public:int studentID;// 派生类构造函数:初始化列表中调用基类构造Student(string n,int a,int id):Person(n, a){ studentID = id; cout <<"Student 带参构造函数被调用"<< endl;}voidshow(){ cout <<"姓名:"<< name <<" 年龄:"<< age <<" 学号:"<< studentID << endl;}};intmain(){ Student s("李四",20,2024002); s.show();return0;}

五、继承的实战案例:员工管理系统

💡 需求:设计一个简单的员工管理系统,包含普通员工 Employee 和经理 Manager 两类角色。Employee 包含姓名、工号、工资属性和工作方法;Manager 继承 Employee,并新增部门属性和管理方法。

5.1 需求分析

  1. 基类 Employee:属性(姓名、工号、工资),方法(工作 work()
  2. 派生类 Manager:公有继承 Employee,新增属性(部门),新增方法(管理 manage()
  3. 要求通过构造函数初始化所有属性,保证数据完整性

5.2 完整代码实现

#include<iostream>#include<string>usingnamespace std;// 基类:普通员工classEmployee{protected: string name;int empID;double salary;public:// 带参构造函数Employee(string n,int id,double sal){ name = n; empID = id; salary = sal; cout <<"Employee 构造函数被调用"<< endl;}// 工作方法voidwork(){ cout <<"员工 "<< name <<"(工号:"<< empID <<")正在工作,月薪:"<< salary << endl;}~Employee(){ cout <<"Employee 析构函数被调用"<< endl;}};// 派生类:经理,公有继承普通员工classManager:publicEmployee{private:// 新增属性:管理部门 string department;public:// 构造函数:初始化列表调用基类构造Manager(string n,int id,double sal, string dep):Employee(n, id, sal){ department = dep; cout <<"Manager 构造函数被调用"<< endl;}// 新增方法:管理voidmanage(){ cout <<"经理 "<< name <<" 管理 "<< department <<" 部门"<< endl;}// 重写基类的 work 方法(方法重写)voidwork(){ cout <<"经理 "<< name <<"(工号:"<< empID <<")正在管理工作,月薪:"<< salary << endl;}~Manager(){ cout <<"Manager 析构函数被调用"<< endl;}};intmain(){// 创建普通员工对象 Employee emp("王五",1001,5000.0); emp.work(); cout <<"-------------------------"<< endl;// 创建经理对象 Manager mgr("赵六",9001,15000.0,"技术部"); mgr.work();// 调用重写后的 work 方法 mgr.manage();// 调用新增的 manage 方法return0;}

5.3 运行结果

Employee 构造函数被调用 员工 王五(工号:1001)正在工作,月薪:5000 ------------------------- Employee 构造函数被调用 Manager 构造函数被调用 经理 赵六(工号:9001)正在管理工作,月薪:15000 经理 赵六 管理 技术部 部门 Manager 析构函数被调用 Employee 析构函数被调用 Employee 析构函数被调用 

六、继承的常见问题与解决方案

6.1 问题1:派生类无法访问基类 private 成员

解决方案

  1. 将基类需要被派生类访问的成员设置为 protected 权限
  2. 在基类中提供 publicget/set 方法,让派生类间接访问 private 成员

6.2 问题2:基类无默认构造函数,派生类编译报错

解决方案
在派生类的构造函数初始化列表中,显式调用基类的带参数构造函数

6.3 问题3:多重继承导致的二义性(钻石问题)

💡 多重继承是指一个派生类同时继承多个基类,容易出现同名成员冲突的问题。
解决方案
使用作用域解析符 :: 明确指定要访问的基类成员

classA{public:voidfunc(){ cout <<"A 的 func 方法"<< endl;}};classB{public:voidfunc(){ cout <<"B 的 func 方法"<< endl;}};classC:publicA,publicB{};intmain(){ C c; c.A::func();// 明确调用 A 类的 func 方法 c.B::func();// 明确调用 B 类的 func 方法return0;}

七、本章总结

✅ 继承的核心是代码复用与功能扩展,派生类可以继承基类的属性和方法,并新增自己的专属内容。
✅ 三种继承方式中,public 继承最常用,其权限规则是“不提升、只限制”。
✅ 继承中的构造顺序是先基后派,析构顺序是先派后基,带参构造需要在初始化列表显式调用。
✅ 多重继承容易引发二义性,可通过作用域解析符解决,实际开发中应谨慎使用多重继承。

Read more

苹果最贵手机要来了!折叠屏iPhone将于9月亮相;部分高校严禁校内使用OpenClaw;黄仁勋预言:传统软件和APP或将消失 | 极客头条

苹果最贵手机要来了!折叠屏iPhone将于9月亮相;部分高校严禁校内使用OpenClaw;黄仁勋预言:传统软件和APP或将消失 | 极客头条

「极客头条」—— 技术人员的新闻圈! ZEEKLOG 的读者朋友们好,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧。(投稿或寻求报道:[email protected]) 整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 一分钟速览新闻点! * 多所高校要求警惕 OpenClaw 安全风险,部分严禁校内使用 * 荣耀 CEO 李健:荣耀机器人全栈自研,将聚焦消费市场 * 马化腾凌晨 2 点发声:还有一批龙虾系产品陆续赶来 * 前快手语言大模型中心负责人张富峥,已加入智源人工智能研究院,负责 LLM 方向 * 最新全球 AI 应用百强榜发布,豆包/DeepSeek/千问上榜 * 苹果折叠 iPhone 将于九月亮相,融合 iPhone 与 iPad 体验

By Ne0inhk
不止“996”!曝硅谷AI创业圈「极限工作制」:每天16小时、凌晨3点下班、周末也在写代码

不止“996”!曝硅谷AI创业圈「极限工作制」:每天16小时、凌晨3点下班、周末也在写代码

编译 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) “如果你周日去旧金山的咖啡馆,会发现几乎每个人都在工作。” 这是 AI 创业公司 Mythril 联合创始人 Sanju Lokuhitige 最近最直观的感受。去年 11 月,他特地搬到旧金山,只为了更接近 AI 创业浪潮的中心。但很快,他也被卷入了这股浪潮带来的另一面——一种越来越极端的工作文化。 Lokuhitige 坦言,他现在几乎每天工作 12 小时,每周 7 天。除了每周少数几场刻意安排的社交活动(主要是为了和创业者们建立联系),其余时间几乎都在写代码、做产品。 “有时候我整整一天都在编程,”他说,“我基本没有什么工作与生活的平衡。”而这样的生活,在如今的 AI 创业圈里并不算罕见。 旧金山 AI 创业圈的真实日常 一位在旧金山一家 AI

By Ne0inhk
黄仁勋公开发文:传统软件开发模式终结,参与AI不必非得拥有计算机博士学位

黄仁勋公开发文:传统软件开发模式终结,参与AI不必非得拥有计算机博士学位

AI 究竟是什么?在 NVIDIA CEO 黄仁勋看来,它早已不只是聊天机器人或某个大模型,而是一种正在迅速成形的“新型基础设施”。 近日,黄仁勋在英伟达官网发布了一篇长文,提出一个颇具形象的比喻——AI 就像一块“五层蛋糕”。从最底层的能源,到芯片、基础设施、模型,再到最上层的应用,人工智能正在形成一整套完整的产业技术栈,并像电力和互联网一样,逐渐成为现代社会的底层能力。 这也是黄仁勋自 2016 年以来公开发表的第七篇长文。在这篇文章中,他从计算机发展史与第一性原理出发,试图解释 AI 技术栈为何会演化成如今的形态,以及为什么全球正在掀起一场规模空前的 AI 基础设施建设。 在他看来,过去几十年的软件大多是预先编写好的程序:人类设计好算法,计算机按指令执行,数据被结构化存储在数据库中,通过精确查询调用。而 AI 的出现打破了这一模式——计算机开始能够理解图像、文本和声音,并根据上下文实时生成答案、推理结果甚至新的内容。 正因为智能不再是预先写好的代码,而是实时生成的能力,支撑它运行的整个计算体系也必须被重新设计。

By Ne0inhk
猛裁1.6万人后,网站再崩6小时、一周4次重大事故!官方“紧急复盘”:跟裁员无关,也不是AI写代码的锅

猛裁1.6万人后,网站再崩6小时、一周4次重大事故!官方“紧急复盘”:跟裁员无关,也不是AI写代码的锅

整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 过去几年里,科技公司几乎都在同一件事上加速:让 AI 参与写代码。 从自动补全、自动生成函数,到直接修改系统配置,生成式 AI 已经逐渐走进真实生产环境。但最近发生在亚马逊的一连串事故,却给整个行业泼了一盆冷水——当 AI 开始真正参与生产环境开发时,事情可能远比想象复杂。 最近,多家媒体披露,本周二亚马逊内部紧急召开了一场工程“深度复盘(deep dive)”会议,专门讨论最近频繁出现的系统故障——其中,一个被反复提及的关键词是:AI 辅助代码。 一周 4 次严重事故,亚马逊内部紧急复盘 事情的起点,是最近一段时间亚马逊系统稳定性明显下降。 负责亚马逊网站技术架构的高级副总裁 Dave Treadwell 在一封内部邮件中坦言:“各位,正如大家可能已经知道的,最近网站及相关基础设施的可用性确实不太理想。” 为此,公司决定把原本每周例行举行的技术会议

By Ne0inhk