如果成员变量不是public,客户唯一能够访问对象的办法就是通过成员函数。如果public接口内的每样东西都是函数,客户就只需要记住使用小括号访问成员。使用函数还可以让你对成员变量的处理有更精确控制。如果你令成员变量为public,每个人都能读写它。但如果你以函数取得或设定其值,你就可以实现出只读、只写、读写访问了:
class AccessLevels {
public:
...
int getReadOnly() const { return readOnly; }
void setReadWrite(int value) { readWrite = value; }
int getReadWrite() { return readWrite; }
void setWriteOnly(int value) { writeOnly = value; }
private:
int noAccess;
int readOnly;
int readWrite;
int writeOnly;
};
如此细微地划分访问控制颇有必要,因为许多成员变量应该被隐藏起来。
将成员变量声明为private还可以实现封装。如果你通过函数访问成员变量,日后可以更改以某个计算替换这个成员变量,而class的客户不会知道内部已经发生了变化。
举个例子,假设你在写一个自动测速程序,当汽车通过,其速度便被计算并填入一个速度收集器内:
class SpeedDataCollection {
...
public:
void addValue(int speed);
double averageSoFar() const;
...
};
将成员变量隐藏在函数接口的背后,可以为所有可能的实现提供弹性。例如这可使得成员变量被读写或被写时轻松通知其他对象,可验证class的约束条件以及函数的前提和时候状态、可以在多线程环江中执行同步控制等等。
protected成员变量的论点十分类似,实际上它和public成员变量的论点相同。语法一致性和细分访问控制等理由也适用于protected数据。而protected成员变量的封装性其实并没有高过public。
对于一个public成员变量,如果我们取消了它,那么所有使用它的代码都会遭到破坏,因此protected成员变量完全没有封装性。对于一个protected成员变量,如果我们取消了它,所有使用它的派生类都会被破坏。因此,protected成员变量就像public成员变量一样缺乏封装性。一旦阿静一个成员变量设计成public或protected,就很难改变那个成员变量所涉及的一切。从封装的角度看,其实只有两种访问权限:private和其他。
请记住
- 切记将成员变量声明为private。这可赋予客户访问数据的一致性、可细分访问控制、允诺约束条件获得保证,并提供class作者以充分的实现弹性。
- protected并不比public更具封装性。