把 C++ 想象成人类社会。 访问权限、继承、友元将无比真实的反应人类社会中的种种关系。 一、类内部访问权限 +---------+ |class | --> 人 +---------+ |public | --> 你能干啥 |protected| --> 你留下啥 |private | --> 你藏了啥 +---------+ |friend | --> 你的圈子 +---------+ 几乎所有人都知道你能干啥,这某种程度上是你在这个社会的价值体现。但这些不相干的人,并不知道你留下了啥,是万贯家财?还是诗书传承?谁知道?你的家人知道(类内部),你的后代知道(子类),你的朋友知道(友元)。至于你藏了些啥,除了你的家人(类内部),可能也只有几位密友(友元)了解。 二、继承时访问权限 +---------+ |Inherits | --> 繁衍后代 +---------+ |public | --> 嫡出 |protected| --> 庶出 |private | --> 私生 +---------+ C++ 的社会没有计划生育,也似乎没有限制一夫一妻。所以存在正房和偏房的问题,嫡长子光明正大(public)的继承了你的财产和光环(public, protected)。其余庶出(protected)的没那么好运了,仅仅能够分到一点财产(protected, protected)。而风流快活的产物——私生子(private)更是可怜,分到的东西谁也说不得,是私密。(private,private)。 class Father { public: int x; protected: int y; private: int z; }; class FirstSon : public Father { // x is public // y is protected // z is not accessible from Father }; class SecondSon : protected Father { // x is protected // y is protected // z is not accessible from Father }; class Illegitimate : private A { // x is private // y is private // z is not accessible from Father }; 三、开始处理各种继承问题(两种访问权限的混搭) class Base { protected: int prot_mem; }; class Sneaky : public Base { friend void clobber(Sneaky &s) { s.j = s.prot_mem = 0; } friend void clobber(Base &b) { b.prot_mem = 0; } // error int j; }; prot_mem 是 Base 的 protected 成员。那么对于 以 public 的姿势继承 Base 的子类 Sneaky 来说,它可以取得该成员(嫡长子)。 而第一个 clobber 作为 Sneaky 的密友,自然也可以取得 Sneaky 的成员,如其自己的 j,以及继承自父类的 prot_mem。 第二个 clobber 作为 Sneaky 的密友,却妄想去直接拿其父亲留下的 prot_mem,这显然是不合理的。 注意这里与上面那个的区别,该密友越过了 Sneaky,直接去拿其父亲的遗物,这是违背了社会法规的。