访问控制: 公用、保护用、私用 (access specifiers)#
公有? 公用!#
public:
、protected
和 private:
往往被翻译成公有、保护有、私有, 但其实描述的不是占有权而是使用权——谁有权去使用这个部分——因而公用、保护用、私用才是更准确的翻译.
以下面的代码为例:
1class Widget {
2 public:
3 int public_value;
4
5 protected:
6 int protected_value;
7
8 private:
9 int private_value;
10};
在类 Widget
内有没有 public_value
、protected_value
、private_value
这三个数据成员? 有! 成员被类占有, 所以才称为类的 "成员".
那么谁能使用这些数据成员呢?
public:
公用. 所有人都能通过这个类用.
1class Widget { 2 public: 3 void function() { 4 value = 0; // 正确: 类自己能用公用的 value 5 } 6 7 int value; 8}; 9 10void function() { 11 Widget widget; 12 widget.value = 0; // 正确: 类外也能用公用的 value 13}
protected:
保护用. 类自己和 继承自这个类的类 (这个类的派生类) 可以用.
private:
私用. 只有类自己能用.
1class Widget { 2 public: 3 void function() { 4 value = 0; // 正确: 类自己能用私用的 value 5 } 6 7 int value; 8}; 9 10void function() { 11 Widget widget; 12 widget.value = 0; // 错误: 类外不能用私用的 value 13}
可见性与可达性 (visibility and accessibility)#
用专业术语来说, public:
、protected:
、private:
等访问控制符描述的是可达性 (accessibility) 而非可见性 (visibility).
例如,
1class Widget {
2 private:
3 int value;
4};
5
6void function() {
7 Widget widget;
8 widget.value = 0; // 错误: value 是 Widget 的私用成员
9}
当编译这段代码时, 编译器将会报错说 "value
是 Widget
的私用成员", 也就是说:
编译器 能看到
value
是Widget
的私用成员, 因而能这么提示;编译器 不能在此处访问
Widget
的value
成员, 因为它是私用的.
访问控制与继承#
继承 (inheritance) 允许我们以一个类作为基底, 在它的基础上派生一个新的类. 其中作为基底的类称为基类 (base class), 派生出的类称为派生类 (derived class).
1class Base {
2 private:
3 int value;
4};
5
6// ↓ 公用继承自 Base 类
7class Derived : public Base {
8 // Derived 继承了 Base::value
9};
既然类 Derived
继承了类 Base
的内容, 那么它就占有 Base
的所有内容. 但是, Derived
能使用 Base::value
吗? 不能, 因为它是私用数据成员, 只能由基类 Base
自己用.
继承方式#
你可能注意到, 上面的代码在 class Derived
之后有一段 : public Base
, 这段的意思是类 Derived
公用继承 自 Base
.
是的, 公用继承! 按照 "派生类要怎样用基类给它的内容", 继承也分为公用继承、保护用继承和私用继承.
: public Base
公用继承. 基类给派生类的内容, 派生类 尽可能 作为公用, 也就是 尽可能 让所有人都能通过派生类能用它.
: protected Base
保护用继承. 基类给派生类的内容, 派生类 尽可能 作为保护用, 也就是 尽可能 只让派生类和继承自派生类的类用它.
: private Base
私用继承. 基类给派生类的内容, 派生类 尽可能 作为私用, 也就是 尽可能 只让派生类自己用它.
什么叫 "尽可能" 呢? 这相当于数学中的求最小值, 而 public > protected > private. 例如,
- 公用继承
对于基类的私用成员, 即便派生类公用继承也没办法使用它: 那个成员是基类私用的, 只有基类自己能用.
对于基类的保护用成员, 即便派生类公用继承而能用它, 但也没办法把它作为公用: 那个成员是基类保护用的, 只有基类和继承自基类的类能使用它.
对于基类的公用成员, 派生类公用继承后, 当然所有人都能通过派生类访问它.
- 私用继承
对于基类的公用成员、保护用成员, 派生类私用继承后, 将仅作为私用.
也就是说, 派生类是在基类的访问控制基础上进行继承. 对于某基类成员, 基类如果不愿意为派生类提供更宽的访问权限, 派生类对该成员最多 (还记得 "尽可能" 吗?) 只能有那样的访问权限.
你只可到这里, 不可越过.
—— 基类访问控制符