C++: 继承基础
最后更新:2026-08-26
假设你写了
Student类和Teacher类,发现它们都有姓名、年龄,但学生有学号,老师有工号。能不能复用
Person类的代码?继承就是干这个的——让类之间形成"父子"关系。
1. 什么是继承?
(1) 1.1 生活中的继承
| 生活场景 | 程序中的对应 |
|---|---|
| 孩子继承父母的特征(眼睛颜色、身高等) | 派生类继承基类的成员 |
| 孩子可以有自己的特征(如特长) | 派生类可以添加新成员 |
继承的本质: 在已有类的基础上,扩展出新类。
(2) 1.2 为什么需要继承?
不用继承(重复代码):
▶ 示例 2:代码示例(难度⭐)
CPP
#include <iostream>
#include <string>
// 学生类
class Student {
std::string name;
int age;
std::string studentId;
};
// 老师类
class Teacher {
std::string name; // ❌ 重复了
int age; // ❌ 重复了
std::string teacherId;
};
输出:
TEXT
📖 仅展示
(程序输出)
用继承(代码复用):
CPP
#include <iostream>
#include <string>
// 基类(父类)
class Person {
public:
std::string name;
int age;
};
// 派生类(子类)
class Student : public Person {
public:
std::string studentId; // 新增成员
};
class Teacher : public Person {
public:
std::string teacherId; // 新增成员
};
2. 继承的基本语法
(1) 2.1 声明派生类
语法:
CPP
class DerivedClassName : inheritanceMode BaseClassName {
// new members
};
示例:
CPP
#include <iostream>
#include <string>
class Person {
public:
std::string name;
int age;
};
// Student 继承 Person
class Student : public Person {
public:
std::string studentId;
};
int main() {
Student s1;
s1.name = "Alice"; // ✅ 继承了 name
s1.age = 20; // ✅ 继承了 age
s1.studentId = "2024001"; // 自己的成员
std::cout << "姓名:" << s1.name << std::endl;
std::cout << "年龄:" << s1.age << std::endl;
std::cout << "学号:" << s1.studentId << std::endl;
return 0;
}
3. 继承方式(访问控制)
(1) 3.1 三种继承方式
| 基类成员 \ 继承方式 | public 继承 | protected 继承 | private 继承 |
|---|---|---|---|
| public 成员 | public(不变) | protected | private |
| protected 成员 | protected | protected | private |
| private 成员 | 不可访问 | 不可访问 | 不可访问 |
💡 重点: 最常用的继承方式是 public 继承。
(2) 3.2 public 继承(推荐)
CPP
#include <iostream>
#include <string>
class Person {
private:
std::string id; // 私有成员:派生类不可访问
protected:
std::string address; // 保护成员:派生类可访问
public:
std::string name; // 公有成员:大家都能访问
void introduce() {
std::cout << "我叫 " << name << std::endl;
}
};
class Student : public Person {
public:
void setAddress(const std::string& addr) {
address = addr; // ✅ 可以访问保护成员
// id = "123"; // ❌ 不可访问私有成员
}
};
int main() {
Student s1;
s1.name = "Alice"; // ✅ 可以访问
// s1.address = "Wuhan"; // ❌ 不可访问(protected)
return 0;
}
4. 构造函数与继承
(1) 4.1 派生类构造函数的调用顺序
规则: 先调用基类构造函数,再调用派生类构造函数。
CPP
#include <iostream>
#include <string>
class Person {
public:
Person() {
std::cout << "Person 构造函数" << std::endl;
}
};
class Student : public Person {
public:
Student() {
std::cout << "Student 构造函数" << std::endl;
}
};
int main() {
Student s1;
return 0;
}
💡 重点: 析构函数的调用顺序相反——先调用派生类析构函数,再调用基类析构函数。
5. 实战:简单的学生管理系统(继承版)
▶ 示例 1:用继承实现(难度⭐⭐)
CPP
#include <iostream>
#include <string>
// 基类
class Person {
protected:
std::string name;
int age;
public:
Person(const std::string& n, int a) : name(n), age(a) {}
void introduce() {
std::cout << "姓名:" << name << ",年龄:" << age << std::endl;
}
};
// 派生类:学生
class Student : public Person {
private:
std::string studentId;
double score;
public:
Student(const std::string& n, int a, const std::string& id, double s)
: Person(n, a), studentId(id), score(s) {}
void introduce() {
Person::introduce(); // 调用基类的 introduce
std::cout << "学号:" << studentId << ",成绩:" << score << std::endl;
}
};
int main() {
Student s1("Alice", 20, "2024001", 92.5);
s1.introduce();
return 0;
}
输出:
TEXT
📖 仅展示
姓名:Alice,年龄:20
学号:2024001,成绩:92.5
❓ 常见问题
Q 继承方式有哪些?应该用哪个?
A > -
public 继承:最常用,保持基类的接口不变 > - protected 继承:不常用 > - private 继承:不常用▶ 示例 3:派生类构造函数(难度⭐)
CPP
#include <iostream>
#include <string>
class Animal {
protected:
std::string name;
public:
Animal(std::string n) : name(n) {}
void speak() { std::cout << name << "发出声音" << std::endl; }
};
class Dog : public Animal {
public:
Dog(std::string n) : Animal(n) {}
void speak() { std::cout << name << "汪汪叫" << std::endl; }
};
int main() {
Dog dog("旺财");
dog.speak();
return 0;
}
输出:
TEXT
📖 仅展示
旺财汪汪叫
💡 提示:派生类构造函数需要调用基类构造函数初始化基类成员。派生类可以重写基类的成员函数。
📖 小节
- 继承让派生类复用基类的代码
- public 继承最常用
- 派生类不能访问基类的
private成员 - 派生类能访问基类的
protected成员 - 构造函数调用顺序:基类 → 派生类
📝 作业
-
基础题 (Difficulty ⭐): 定义一个
Animal基类,包含name成员。让Dog和Cat类继承它。 -
进阶题 (Difficulty ⭐⭐): 扩展上面的程序,给
Animal添加void speak()虚函数(后面会学),让Dog和Cat重写它。 -
挑战题 (Difficulty ⭐⭐⭐): 设计一个图书馆管理系统的类层次结构:
-
Person(姓名、年龄) -
Student继承Person(学号、借阅数量) -
Teacher继承Person(工号、借阅数量) -
实现借阅和归还功能。
-
继承:派生类拥有基类的所有成员
- public/protected/private 继承控制访问权限
- 派生类构造函数调用基类构造函数
- is-a 关系:派生类是基类的一种
- 菱形继承需用虚继承解决二义性
6. 🚀 下一步
学会了继承基础,接下来我们学习 多态(第32课)—— 让基类指针能调用派生类的函数,实现"一个接口,多种实现"!