CppCoreGuidelines C.134 确保非const的成员数据有同级别的访问层级
C.134: Ensure all non-const data members have the same access level
理由
避免逻辑混淆导致错误。如果非 const 成员数据的访问层级不一样,我们就不太懂这个类型到底要做什么。这个类型维护一个不变式约束?还是只不过是一组值的集合?
讨论
核心问题是:哪些代码负责维护变量的有意义和正确的值?
有两种不同的成员数据:
- A:不参与对象的不变式约束的成员数据,任何数据值的组合都是合法的。
- B:参与对象的不变式约束的成员数据。只有某些值的组合是有意义的。(不然就不叫不变式)。因此,任何访问这些变量的代码都要知道其中的隐含的不变式约束和语义。而且代码需要知道并实现什么样的规则能保证值是正确的。
A 类数据成员只要 public 就可以了(或者,少数情况下,你只想要派生类能看到,设置成 protected )。他们不需要封装。系统中所有代码都可以访问并进行操作。
B 类数据应该是 private 或 const 。因为对它们来说,封装很重要。如果他们不是 private ,不是 const ,意味着对象不能控制自己的状态:该类外部,其他不受限制的代码需要知道类的不变式约束,并参与维护。如果数据成员是公开的,那么所有调用到该类的地方都需要维护类的约束;如果数据成员是
protected ,那么当前以及未来派生类的所有代码要参与维护。这样就会使得代码很脆弱、互相紧耦合,很快会成为代码维护的噩梦。任何不经意地把数据成员得值设置成无效的或不对的组合的时候,就会破坏对象的不变式,导致后续的使用出问题。
大部分类要么全是 A 要么全是 B:
- 全
public:如果你在编写一组没有不变式关系的变量的聚合的时候,所有变量应该是公开public的。 - 全
private:如果你写的某个类维护某种不变式关系,那么所有非const的变量都应该是private,需要封装起来。
例外
偶尔的,某些类会混合 A 和 B。通常是为了调试。一个封装的对象可能有一些非 const 的调试数据。这些数据不算类的不变式,所以属于 A 类。这些数据也不是对象的部分值或有意义的状态。这种情况,A 类部分的数据就当作公开数据处理(或者 protected ,如果只想在派生类中访问)。B 类部分的数据仍然作为 B 类数据对待,要么是 private 要么是 const 。
强化
- 标注非
const数据成员有不同的访问层级的类