class D 的对象由 2 个独立的部分组成:
part containing members of B
part containing members of D
这就是为什么我们这样做时对象切片的概念起作用的原因:
D objD;
B objB = objD;
现在我们可以通过objB 从object of class D 内部访问part containing members of B。编译器记住或可以区分class D 中的两个部分。所以编译器知道通过什么来访问什么。
friend class F; 内的 class B 语句只是告诉 member functions of class F 可以访问 class B 的 private, protected and public 成员。也就是说,对于member functions of class F,class B 的所有成员都是public。
实际上,在每个类中都包含三个可访问性部分:
public
protected
private
所以当我们声明一些class B:
class B
{
public:
int a;
protected:
int b;
public:
int c;
};
然后在 B 类中创建以下 3 个部分,如上所示。
现在当我们声明一些class F 是friend 的class B 时:
class B
{
friend class F;
private:
int a;
protected:
int b;
public:
int c;
};
然后编译器创建如下部分:
class B
{
friend class F;
private:
int a;
protected:
int b;
public:
int c;
//int a; only for member functions of class F
//int b; only for member functions of class F
};
请注意,int a; 和 int b; 现在对于 member functions 的 class F 是公开的。
现在,当 class D 从 class B 派生出 publicly 时,class B 的 public 部分变为 class D 的 public 部分。同样,class B 的 protected 部分变为 class D 的 protected 部分。因此,class B 的public 部分可以通过class D 的对象访问。由于B::a; 和B::b; 在members functions of class F 的公共部分中,因此B::a 和B::b 可以通过class D 的对象访问。另请注意,虽然int a; 和int b; 派生后成为class D 的成员,但编译器仍然能够区分它们并将它们视为part of class B。
现在,当 class D 派生自 class B 的 privately 时,class B 的 public 部分将变为 class D 的 private 部分。同样,class B 的 protected 部分成为 class D 的受保护部分。因此,现在class B 内部的public 部分无法通过class D 的对象访问。回想一下,class B、B::a; 和 B::b; 最初在 members functions of class F 的公共部分,但在推导 private 之后,class B 的成员即 B::a 和 B::b 现在在class D。因此,B::a 和B::b 不能通过class D 的对象访问。另请注意,虽然在推导 int a; 和 int b; 之后成为 class D 的成员,但编译器仍然能够区分它们并将它们视为 part of class B。派生后class B的一些成员的可访问性和规则发生了变化。
由于这个问题在某种程度上与public, protected and private 推导的效果有关,因此为了完整性,请参阅:
Why can a derived class not access a protected member of its base class through a pointer to base?