在理解了内联函数对效率的影响之后,本篇转向类的设计哲学核心,那就是封装。

访问级别:public 与 private 关键字

public 公有区域

标记后的成员所有代码都可直接访问。通常用于对外的接口函数。

private 私有区域

仅允许本类成员函数访问,类外部代码无法访问。通常用于数据成员和内部辅助函数。

声明方式与区域划分:

image

区域可以任意交错,但通常将 public 接口放在前面,提高可读性。

如果没有访问控制,所有成员都默认是公有,外部代码可以随意修改对象内部数据,会导致严重问题。

  • 数据一致性被破坏:时钟类的 hour 被直接设为 25,进入非法状态
  • 接口与实现耦合:数据成员名或类型改变时,所有外部代码都需要修改
  • 安全漏洞:敏感数据(密码、余额)可能被意外读取或篡改
  • private 强制外部通过公有成员函数间接操作,可加入合法性检查

针对类而非对象:同一类的不同对象之间,可以互相访问对方的私有成员(前提是在该类的成员函数内)。
protected 暂不涉及:第三种访问级别 protected 用于继承场景,本篇不深入讨论。

封装落地:数据私有化,通过成员函数访问

所有数据成员都应声明为 private,然后提供公有的取值函数(getter)和设值函数(setter)作为对外接口。这称为封装(Encapsulation)。

以复数类(Complex)为例:

❌错误示范

1
2
3
4
5
6
7
8
9
class Complex {
public:
double real; // ❌ 公有数据
double imag;
};

Complex c;
c.real = 3.5; // 外部直接修改
c.imag = 2.1; // 无任何检查

✔️正确示范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Complex {
private:
double real; // ✅ 私有数据
double imag;
public:
void setReal(double r) { real = r; }
void setImag(double i) { imag = i; }
double getReal() const { return real; }
double getImag() const { return imag; }
};

Complex c;
c.setReal(3.5); // ✅ 通过接口访问
c.setImag(2.1);

封装带来的核心收益

image