将成员变量声明为private——条款22

        首先看看为什么成员变量不该是public,然后看看所有反对public成员变量的论点同样适用于protected成员变量。最后导出一个结论:成员变量应该是private。获得这个结论后,本条款就大功告成了。

        让我们从语法一致性开始(同时请见条款18)。如果成员变量不是public,客户唯一能够访问对象的办法就是通过成员函数。如果public接口内的每样东西都是函数,客户就不需要再打算访问class成员时迷惑地试着记住是否该使用小括号(圆括号)。他们只要做就是了,因为每样东西都是函数。

        使用private更大的便利就是封装,如果通过函数访问成员变量,日后可以改以某个计算替换这个成员变量,而这个过程对class客户是透明的。

        例如,你正在写一个自动测速程序,当汽车通过,其速度便被计算并填入一个速度收集器内:

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

        现在让我们考虑成员函数averageSoFar。做法之一是在class内设计一个成员变量,记录至今以来所有速度的平均值。当averageSoFar被调用,只需返回那个成员变量就好。另一个做法是令averageSoFar每次被调用时重新计算平均值,此函数有权利调取收集器内的每一笔速度值。

        上述第一种做法(随时保持平均值)会使每一个SpeedDataCollection对象变大,因为你必须为用来存放目前平均值、累积总量、数据点数的每一个成员变量分配空间,然而averageSoFar却可因此十分高效:它可以只是一个返回目前平均值的inline函数(见条款30).相反地,“被询问才计算平均值”会使得averageSoFar执行较慢,但每一个SpeedDataCollection对象比较小。

        上面两种方式不能完全说哪一种好,跟实机运行环境有关,如果内存吃紧的机器上用“每次需要时才计算”或许比较好。但在一个频繁需要平均值的程序中,如果反应速度非常重要,内存不是重点,这时候“随时维持一个当下平均值”往往更好。

        封装的重要性比你最初见到它时还重要。如果你对客户隐藏成员变量(也就是封装它们),你可以确保class的约束条件总是会获得维护,因为只有成员函数可以影响它们。犹有进者,你保留了日后变更实现的权利。如果不隐藏它们,之后改变任何public时都会破坏太多客户代码。public意味着不封装,而几乎可以说,不封装意味不可改变,特别是对被广泛使用的classes而言。

        protected成员变量的论点十分类似。实际上它和public成员变量的论点相同,虽然或许最初看起来不是一回事。“语法一致性”和“细微划分之访问控制”等理由显然也适用于protected数据,就像对public一样适用。但封装呢?protected成员变量的封装性是不是高过public成员变量?答案令人惊讶:并非如此。

        条款23会告诉你,某些东西的封装性与“当其内容改变时可能造成的代码破坏量”成反比。因此,成员变量的封装性与“成员变量的内容改变时所破坏的代码数量”成反比。所谓改变,也许是从class中移除它(或许这有利于计算,就像上述的averageSoFar)。

        假如我们有一个public成员变量,而我们最终取消了它。多少代码可能会被破坏呢?唔,所有使用它的客户码都会被破坏,而那是一个不可知的大量。因此public成员变量完全没有封装性。假设我们有一个protected成员变量,而我们最终取消了它,有多少代码被破坏?唔,所有使用它的derived classes都会被破坏,那往往也是一个不可知的大量。因此,protected成员变量就像public成员变量一样缺乏封装性。虽然这个结论有点违反直观,但经验丰富的程序库作者会告诉你,它是真的。

请记住

  • 切记将成员变量声明为private。这可赋予客户访问数据的一致性、可细微划分访问控制、允诺约束条件获得保证,并提供class作者以充分的实现弹性。
  • protected并不比public更具封装性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值