0%

[Effective C++ 笔记]条款 22. 将成员变量声明为 private

简介

  • 将成员变量声明为 private,可以提供使用者访问数据的一致性,精确控制访问权限,并给作者提供充分的实现弹性
  • protected 并不比 public 更具有封装性

不对成员变量采用 public 的理由

语法一致性

如果对成员变量采用 public,那么使用者在使用这个类的时候会有两种方法,调用函数或者访问对象;而如果使用 private,那么要访问成员变量只能通过函数进行访问,因此保持了使用时候的语法一致性。不需要花多余的精力去记忆每个变量的具体情况。

对成员变量处理缺少准确控制

如果对成员变量采用 public,那么每个成员变量都是可供读写的,没办法对其实施精确权限控制。使用 private 时可以通过是否为这个变量提供 setter 或 getter 函数来控制其的读/写权限。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class AccessLevels {
public:
// ...
int getReadOnly() const { return readOnly; }
void setReadWrite(int value) { readWrite = value; }
int getReadWrite() const { return readWrite; }
void setWriteOnly(int value) { WriteOnly = value; }

private:
int noAccess; // 不提供任何访问权限
int readOnly; // 只读访问
int readWrite; // 读写访问
int writeOnly; // 只写访问
};

不利于封装

如果对成员变量采用 public,那么必须要考虑到使用者会直接在其代码中使用这个变量。并且由于使用者是直接访问该变量,我们没办法在成员变量被读时通知其他变量。这在有的时候不会很方便,例如:

1
2
3
4
5
6
class SpeedDataCollection {
// ...
public:
void addValue(int speed); // 添加一笔新数据
double averageSoFar() const;// 返回平均速度
}

对于 averageSoFar() 而言,我们既可以让其每次计算平均值,也可以在内部存储一个平均值变量,在函数调用时直接返回该变量。这两种实现方式各有优劣,取决于我们更看重时间还是希望类占用空间最小。但是如果我们让成员变量作为 public 的话,就没办法在这两种实现方式间进行自由的更换(否则会导致外部代码直接调用平均值的部分报错)。因此将成员变量隐藏在借口函数的背后可以为所有实现提供一定弹性。

不对成员变量采用 protected 的理由

不使用 public 的理由基本上也在 protected 上也是成立的。无非是外部会影响的代码从所有使用这个类的代码变为所有使用这个类的派生类而已。从封装性而言,如果我们使用 public 变量一段时间后取消掉它,受影响的时候所有使用它的客户码,对于 protected 变量,受影响的则是所有使用它的派生类。因此 protected 的封装性也并不比 public 高。因此从封装的角度而言,访问权限只有两种,private(提供封装) 和其他(不提供封装)。

结论

  • 将成员变量声明为 private,可以提供使用者访问数据的一致性,精确控制访问权限,并给作者提供充分的实现弹性
  • protected 并不比 public 更具有封装性

其他