23.将成员变量声明为private

为什么不使用public成员变量

  1. 语义一致性
    如果成员变量都不是public,那我们必然是通过成员函数来访问对象,所以再也不用担心什么时候用接口,什么时候用属性了。
    另外,使用函数可以对变量进行更加精准的控制,你完全可以实现只读,读写,或者不予读写,甚至只写操作。举例而言:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class AccessLevels{
    public:
    ...
    int getReadOnly() const{return readOnly;}
    void setReadWrite(int value) {readWrite=value;}
    int getReadWrite() const {return readWrite;}
    void setWriteOnly(writeOnly=value;}
    private:
    int noAccess;//禁止访问
    int readOnly;//只读
    int readWrite;//读写
    int writeOnly;//只写
    }
  2. 封装性
    将成员变量隐藏在函数接口之后,可以为“所有实现的可能”提供弹性,我们可以在不改变接口的同时更改实现,从而保证了用户只需要在重新编译后即可享有与原先不同的体验。(Effective C++ 31 甚至提出了编译分离)
    封装的重要程度可能比你想的还要更加高一些,如果你对客户隐藏了成员变量,那么至少可以保证class的约束条件总能获得维护,因为只有成员函数可以影响它们,并且开发者保留了日后变更实现的权利。如果不进行封装,那么客户码中将充斥着大量的成员变量,这也意味着我们无法随意地更改原有程序,因为每一次改动都可能造成客户端失效。public意味着不封装,不封装意味着不可改变,因为你一变用户也要跟着变。

protected的封装性

</br>
可能你会认为protected的封装性要高于public,但事实并非如此。因为所有使用了该变量的derived classes都遭到了破坏。一旦你将某个成员变量设为public或protected,并且随后交付客户使用,那你在今后就很难改变该变量所涉及的一切,除非你愿意付出重写、重新测试、重新编文档、重新编译的代价。
从封装的角度而言,访问权限只有两种:private(提供封装)和其他(不提供封装)。


总结

  1. 将成员变量声明为privte。这可赋予客户语义一致性,访问权限控制,并且令class作者拥有充分的实现弹性。
  2. protected并不比public更具封装性