访问控制: 公用、保护用、私用 (access specifiers)

访问控制: 公用、保护用、私用 (access specifiers)#

公有? 公用!#

public:protectedprivate: 往往被翻译成公有、保护有、私有, 但其实描述的不是占有权而是使用权——谁有权去使用这个部分——因而公用、保护用、私用才是更准确的翻译.

以下面的代码为例:

 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_valueprotected_valueprivate_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}

当编译这段代码时, 编译器将会报错说 "valueWidget 的私用成员", 也就是说:

  • 编译器 能看到 valueWidget 的私用成员, 因而能这么提示;

  • 编译器 不能在此处访问 Widgetvalue 成员, 因为它是私用的.

访问控制与继承#

继承 (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. 例如,

公用继承
  • 对于基类的私用成员, 即便派生类公用继承也没办法使用它: 那个成员是基类私用的, 只有基类自己能用.

  • 对于基类的保护用成员, 即便派生类公用继承而能用它, 但也没办法把它作为公用: 那个成员是基类保护用的, 只有基类和继承自基类的类能使用它.

  • 对于基类的公用成员, 派生类公用继承后, 当然所有人都能通过派生类访问它.

私用继承
  • 对于基类的公用成员、保护用成员, 派生类私用继承后, 将仅作为私用.

也就是说, 派生类是在基类的访问控制基础上进行继承. 对于某基类成员, 基类如果不愿意为派生类提供更宽的访问权限, 派生类对该成员最多 (还记得 "尽可能" 吗?) 只能有那样的访问权限.

你只可到这里, 不可越过.

—— 基类访问控制符