C++ 继承:面向对象的代码复用核心机制
C++ 继承的核心概念、语法及三种访问权限控制方式(public/protected/private)。详细阐述了基类与派生类的构造与析构顺序规则,并通过员工管理系统案例演示了实际应用场景。最后总结了多重继承的二义性解决方案及常见问题处理技巧,旨在帮助开发者掌握面向对象代码复用的关键机制。

C++ 继承的核心概念、语法及三种访问权限控制方式(public/protected/private)。详细阐述了基类与派生类的构造与析构顺序规则,并通过员工管理系统案例演示了实际应用场景。最后总结了多重继承的二义性解决方案及常见问题处理技巧,旨在帮助开发者掌握面向对象代码复用的关键机制。

💡 学习目标:掌握继承的基本语法与核心特性,理解不同继承方式的访问权限控制,能够通过继承实现代码复用与扩展。 💡 学习重点:继承的语法格式、三种继承方式的区别、基类与派生类的关系、继承中的构造与析构顺序。
✅ 结论:继承是 C++ 面向对象三大特性之一,允许一个类派生类继承另一个类基类的属性和行为,实现代码复用,同时支持派生类在基类基础上扩展新功能。
继承的核心价值体现在两个方面:
生活中的继承示例:学生和老师都属于'人',都有姓名、年龄等属性和吃饭、睡觉等行为。可以先定义 Person 基类,再让 Student 和 Teacher 继承 Person,并各自扩展专属功能。
class 派生类名 : 继承方式 基类名 {
// 派生类的成员
};
public、protected、private 三种💡 以 Person 作为基类,Student 作为派生类为例,演示继承的基本用法
#include <iostream>
#include <string>
using namespace std;
// 基类:人
class Person {
public:
string name;
int age;
void eat() {
cout << name << " 正在吃饭" << endl;
}
void sleep() {
cout << name << " 正在睡觉" << endl;
}
};
// 派生类:学生,公有继承 Person
class Student : public Person {
public:
// 派生类新增属性:学号
int studentID;
// 派生类新增方法:学习
void study() {
cout << name << " 正在学习,学号:" << studentID << endl;
}
};
int main() {
// 创建派生类对象 Student s
// 访问从基类继承的属性
s.name = "张三";
s.age = 18;
// 访问派生类自身的属性
s.studentID = 2024001;
// 调用从基类继承的方法
s.eat();
s.sleep();
// 调用派生类自身的方法
s.study();
return 0;
}
张三 正在吃饭 张三 正在睡觉 张三 正在学习,学号:2024001
💡 继承方式直接影响基类成员在派生类中的访问权限,核心规则是继承方式不会提升成员的访问权限,只会限制或保持原有权限。
| 基类成员权限 | public 继承 | protected 继承 | private 继承 |
|---|---|---|---|
| public | public | protected | private |
| protected | protected | protected | private |
| private | 不可访问 | 不可访问 | 不可访问 |
⚠️ 核心注意点
private 成员在派生类中始终不可直接访问,只能通过基类的 public 或 protected 方法间接访问#include <iostream>
#include <string>
using namespace std;
class Base {
public:
int pub;
protected:
int pro;
private:
int pri
};
// 公有继承
class PubDerived : public Base {
public:
void show() {
pub = 10; // 合法:public 继承后仍为 public
pro = 20; // 合法:public 继承后为 protected
// pri = 30; // 非法:基类 private 成员不可访问
}
};
int main() {
PubDerived pd;
pd.pub = 100; // 合法:类外可访问 public 成员
// pd.pro = 200; // 非法:protected 成员类外不可访问
return 0;
}
class ProDerived : protected Base {
public:
void show() {
pub = 10; // 合法:protected 继承后为 protected
pro = 20; // 合法:protected 继承后仍为 protected
// pri = 30; // 非法:基类 private 成员不可访问
}
};
int main() {
ProDerived prd;
// prd.pub = 100; // 非法:protected 继承后 pub 变为 protected,类外不可访问
return 0;
}
class PriDerived : private Base {
public:
void show() {
pub = 10; // 合法:private 继承后为 private
pro = 20; // 合法:private 继承后为 private
// pri = 30; // 非法:基类 private 成员不可访问
}
};
int main() {
PriDerived prd;
// prd.pub = 100; // 非法:private 继承后 pub 变为 private,类外不可访问
return 0;
}
💡 派生类对象的创建和销毁过程,会涉及基类和派生类的构造函数、析构函数调用,其顺序有严格的规则。
✅ 构造顺序:先调用基类的构造函数,再调用派生类的构造函数
✅ 析构顺序:先调用派生类的析构函数,再调用基类的析构函数
简单记忆:构造先基后派,析构先派后基
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
Person() {
cout << "Person 基类构造函数被调用" << endl;
}
~Person() {
cout << "Person 基类析构函数被调用" << endl;
}
};
class Student : public Person {
public:
Student() {
cout << "Student 派生类构造函数被调用" << endl;
}
~Student() {
cout << "Student 派生类析构函数被调用" << endl;
}
};
int main() {
// 创建派生类对象 Student s
// 函数结束时对象销毁,自动调用析构函数
return 0;
}
Person 基类构造函数被调用 Student 派生类构造函数被调用 Student 派生类析构函数被调用 Person 基类析构函数被调用
当基类只有带参数的构造函数时,派生类必须在初始化列表中显式调用基类的构造函数。
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
string name;
int age;
// 基类带参数构造函数
Person(string n, int a) {
name = n;
age = a;
cout << "Person 带参构造函数被调用" << endl;
}
};
class Student : public Person {
public:
int studentID;
// 派生类构造函数:初始化列表中调用基类构造
Student(string n, int a, int id) : Person(n, a) {
studentID = id;
cout << "Student 带参构造函数被调用" << endl;
}
void show() {
cout << "姓名:" << name << " 年龄:" << age << " 学号:" << studentID << endl;
}
};
int main() {
Student s("李四", 20, 2024002);
s.show();
return 0;
}
💡 需求:设计一个简单的员工管理系统,包含普通员工 Employee 和经理 Manager 两类角色。Employee 包含姓名、工号、工资属性和工作方法;Manager 继承 Employee,并新增部门属性和管理方法。
Employee:属性(姓名、工号、工资),方法(工作 work())Manager:公有继承 Employee,新增属性(部门),新增方法(管理 manage())#include <iostream>
#include <string>
using namespace std;
// 基类:普通员工
class Employee {
protected:
string name;
int empID;
double salary;
public:
// 带参构造函数
Employee(string n, int id, double sal) {
name = n;
empID = id;
salary = sal;
cout << "Employee 构造函数被调用" << endl;
}
// 工作方法
void work() {
cout << "员工 " << name << "(工号:" << empID << ")正在工作,月薪:" << salary << endl;
}
~Employee() {
cout << "Employee 析构函数被调用" << endl;
}
};
// 派生类:经理,公有继承普通员工
class Manager : public Employee {
private:
// 新增属性:管理部门
string department;
public:
// 构造函数:初始化列表调用基类构造
Manager(string n, int id, double sal, string dep) : Employee(n, id, sal) {
department = dep;
cout << "Manager 构造函数被调用" << endl;
}
// 新增方法:管理
void manage() {
cout << "经理 " << name << " 管理 " << department << " 部门" << endl;
}
// 重写基类的 work 方法(方法重写)
void work() {
cout << "经理 " << name << "(工号:" << empID << ")正在管理工作,月薪:" << salary << endl;
}
~Manager() {
cout << "Manager 析构函数被调用" << endl;
}
};
int main() {
// 创建普通员工对象 Employee emp
Employee emp("王五", 1001, 5000.0);
emp.work();
cout << "-------------------------" << endl;
// 创建经理对象 Manager mgr
Manager mgr("赵六", 9001, 15000.0, "技术部");
mgr.work(); // 调用重写后的 work 方法
mgr.manage(); // 调用新增的 manage 方法
return 0;
}
Employee 构造函数被调用 员工 王五(工号:1001)正在工作,月薪:5000 ------------------------- Employee 构造函数被调用 Manager 构造函数被调用 经理 赵六(工号:9001)正在管理工作,月薪:15000 经理 赵六 管理 技术部 部门 Manager 析构函数被调用 Employee 析构函数被调用 Employee 析构函数被调用
解决方案:
protected 权限public 的 get/set 方法,让派生类间接访问 private 成员解决方案:
在派生类的构造函数初始化列表中,显式调用基类的带参数构造函数
💡 多重继承是指一个派生类同时继承多个基类,容易出现同名成员冲突的问题。
解决方案:
使用作用域解析符 :: 明确指定要访问的基类成员
class A {
public:
void func() {
cout << "A 的 func 方法" << endl;
}
};
class B {
public:
void func() {
cout << "B 的 func 方法" << endl;
}
};
class C : public A, public B {};
int main() {
C c;
c.A::func(); // 明确调用 A 类的 func 方法
c.B::func(); // 明确调用 B 类的 func 方法
return 0;
}
✅ 继承的核心是代码复用与功能扩展,派生类可以继承基类的属性和方法,并新增自己的专属内容。
✅ 三种继承方式中,public 继承最常用,其权限规则是'不提升、只限制'。
✅ 继承中的构造顺序是先基后派,析构顺序是先派后基,带参构造需要在初始化列表显式调用。
✅ 多重继承容易引发二义性,可通过作用域解析符解决,实际开发中应谨慎使用多重继承。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online