C++ 中的 封装(Encapsulation) 和 继承(Inheritance) 是面向对象编程(OOP)的两大核心特性(另外两个是多态和抽象)。下
🔐 一、封装(Encapsulation)
封装 是将数据(成员变量)和操作数据的函数(成员方法)捆绑在一起,并隐藏对象的内部实现细节,只通过公开的接口(public methods)与外界交互。
🎯 目的:提高安全性、降低耦合、增强可维护性。
🔑 封装的关键:访问控制
C++ 通过 访问修饰符(Access Modifiers) 来控制类成员的访问权限:
修饰符 访问权限
public 任何地方都可以访问
private 只有类内部可以访问(默认)
protected 类内部和子类可以访问
📌 示例:封装一个 Student 类
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
int age;
double score;
public:
// 构造函数
Student(string n, int a, double s) {
setName(n);
setAge(a);
setScore(s);
}
// 公共接口(getter 和 setter)
void setName(string n) {
if (n.length() > 1) {
name = n;
} else {
cout << "名字太短!" << endl;
}
}
string getName() const {
return name;
}
void setAge(int a) {
if (a > 0 && a < 150) {
age = a;
} else {
cout << "年龄不合法!" << endl;
}
}
int getAge() const {
return age;
}
void setScore(double s) {
if (s >= 0 && s <= 100) {
score = s;
} else {
cout << "分数必须在 0~100 之间!" << endl;
}
}
double getScore() const {
return score;
}
// 打印信息
void display() const {
cout << "姓名: " << name << ", 年龄: " << age << ", 分数: " << score << endl;
}
};
int main() {
Student s("张三", 20, 95.5);
s.display();
// 通过接口修改数据
s.setAge(25);
s.setScore(105); // 会提示错误
s.display();
return 0;
}
✅ 封装的好处:
外界不能直接修改 age 或 score,必须通过 setAge()、setScore() 进行合法性检查。
内部实现可以改变(比如把 string name 改成 char*),但接口不变,不影响外部代码。
🔁 二、继承(Inheritance)
继承 允许一个类(子类 / 派生类)继承另一个类(父类 / 基类)的属性和方法,实现代码的重用和扩展。
🎯 目的:避免重复代码,建立类之间的层次关系。
🔤 语法格式:
class 派生类名 : 访问控制 基类名 {
// 新增成员
};
继承方式(访问控制):
public:最常用,基类的 public 成员在派生类中仍是 public。
protected:基类的 public 变成 protected。
private:基类成员在派生类中都变成 private(不常用)。
📌 示例:学生和大学生
#include <iostream>
#include <string>
using namespace std;
// 基类:学生
class Student {
protected: // 用 protected,子类可以访问
string name;
int age;
public:
Student(string n, int a) : name(n), age(a) {}
void study() {
cout << name << " 正在学习。" << endl;
}
void display() const {
cout << "姓名: " << name << ", 年龄: " << age;
}
};
// 派生类:大学生(继承自 Student)
class CollegeStudent : public Student {
private:
string major; // 新增属性
public:
CollegeStudent(string n, int a, string m)
: Student(n, a), major(m) {} // 调用基类构造函数
// 新增方法
void research() {
cout << name << " 正在做 " << major << " 方向的研究。" << endl;
}
// 重写 display 方法
void display() const override {
Student::display(); // 调用基类方法
cout << ", 专业: " << major << endl;
}
};
int main() {
CollegeStudent cs("李四", 22, "计算机科学");
cs.display(); // 姓名: 李四, 年龄: 22, 专业: 计算机科学
cs.study(); // 李四 正在学习。
cs.research(); // 李四 正在做 计算机科学 方向的研究。
return 0;
}
✅ 继承的好处:
CollegeStudent 自动拥有了 name、age、study() 等成员。
可以添加新的属性(major)和方法(research())。
支持 方法重写(Override),实现多态(后续可学)。
🔁 封装 vs 继承 对比
特性 封装(Encapsulation) 继承(Inheritance)
目的 隐藏实现,保护数据 代码复用,扩展功能
关系 类的内部组织 类之间的层次关系
关键词 private, public, protected :(冒号), class Derived : public Base
示例 把数据设为 private,用函数访问 子类继承父类的属性和方法
✅ 总结
概念 核心思想 关键作用
封装 “把东西包起来” 安全、可控、易维护
继承 “子承父业” 复用、扩展、建立类族
💡 编程建议:
优先使用 封装 来设计每个类。
当多个类有共同特征时,考虑使用 继承 抽象出基类。
避免过度继承,优先考虑“组合”(Composition)而非“继承”。
如果你想继续了解:
多态(Polymorphism)
虚函数(virtual)
抽象类(Abstract Class)