C++条款 将成员变量声明为private 13/55

将成员变量声明为private

Declare date members private

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

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

或许你不认为一致性的理由足以让人信服,那个这个事实如何:使用函数会让你对成员变量的处理有更精确的控制。如果你令成员变量为public,每个人都可以读写它,但如果你以函数取得或设定其值,你就可以实现出“不准访问”、“只读访问”以及“读写访问”甚至“准写访问”:

class AccessLevels{
public:
    ...
    int getReadOnly()const { return readOnlay;}
    void setReadWrite(int value) { readWrite = value;}
    int getReadWrite() const { return readWrite;}
    void setWriteOnly(int value) { writeOnly = value;}
private:
    int noAccess;    //对此int无任何访问动作
    int readOnly;    //对此int做只读访问
    int readWrite;    //对此int做读写访问
    int writeOnly;    //对此int做唯写访问
};

如此细微地划分访问控制函数颇有必要,因为许多成员变量应该被隐藏起来。

还是不够说服你?是时候端出大口径武器的时候了:封装。如果你通过函数访问成员变量,日后可改以某个计算替换这个成员变量,而class客户一点也不知道class的内部实现已经起了变化。

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

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

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

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

至于孰优孰劣,还是视情况而定。

将成员变量隐藏在函数接口的背后,可以为“所有可能的实现”提供弹性。例如这可使得成员变量被读或被写时轻松通知其他对象、可以验证class的约束条件以及函数的前提和事后状态、可以在多线程环境中执行同步控制.....等等。

封装的重要性比你最初见到它时还重要。如果你对客户隐藏成员变量,你可以确保class的约束条件总是会获得维护,因为只有成员函数可以影响它们。犹有进者,你保留了日后变更实现的权利。

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

成员变量的封装性与“成员变量内容改变时所破坏的代码数量”成反比。所谓改变,也许是从class中移除它。

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

总结:

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

​​​​​​​编于04/06/2019 16:11

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值