问题描述
我很惊讶下面的代码编译。
I'm surprised that the code below compiles.
似乎与(公共继承的)基类成为朋友的类可以访问基类的成员提供了派生类的实例。
It seems that a class befriended to the (publicly inherited) base class can access a member of the base class provided an instance of the derived class.
如果继承更改为 private ,则编译失败。
If the inheritance is changed to private then compilation fails.
简而言之, d.b_var 如何在 F :: func(D& d)中有效?
#include <iostream> #include <string> using namespace std; class B{ int b_var; friend class F; }; class D: public B{ int d_var; }; class F{ public: void func(D &d){ d.b_var = 5; } }; int main() { cout<<"fine"; }
推荐答案
<$ c $的对象c> D类由2个独立部分组成:
Object of class D is composed of 2 separate parts :
part containing members of B part containing members of D
这就是为什么对象切片的概念在我们这样做时有效:
That why the concept of object slicing works when we do:
D objD; B objB = objD;
现在我们可以从D类对象内部访问,部分包含B 的成员,通过 objB 。编译器会记住或者可以区分 class D 中的两个部分。所以编译器知道通过什么访问什么。
Now we can access from inside object of class D, the part containing members of B via objB. Compiler remembers or can distinguish between the two parts inside class D. So compiler know what is being accessed via what.
语句朋友类F; 在 B类只是告诉类F 的成员函数可以访问 private,protected和public B类成员。也就是说,对于类F的成员函数 class B 的所有成员都是 public 。
The statement friend class F; inside class B simply tells that member functions of class F can accesses the private, protected and public members of class B. That is, for member functions of class F all the members of class B are public.
实际上,在每个课程中,有三个部分可以访问:
Actually, inside every class there are three sections w.r.t accessibility:
public protected private
所以当我们声明一些 B级:
class B { public: int a; protected: int b; public: int c; };
然后在类 B 如上所示。
现在我们声明一些类F 成为的朋友 B类:
Now when we declare some class F to be a friend of class B:
class B { friend class F; private: int a; protected: int b; public: int c; };
然后编译器按如下方式创建部分:
then the compiler creates the sections as follows:
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; 现在公开成员函数 class F 。
Note that int a; and int b; are now public for member functions of class F.
现在当 D类从< c>公开从< class B 然后 class B 的 public 部分变为 public class D 的部分。类似地, class B 的 protected 部分变为 protected 部分 D类。因此,可以通过 class D <的对象访问 class B 的 public 部分/ code>。因为 B :: a; 和 B :: b; 在的公共部分类F 的成员函数,因此 B :: a 和 B :: b 可以可以通过 class D 的对象访问。另请注意,虽然在派生后 int a; 和 int b; 成为类D的成员,仍然是编译器能够区分它们并认为它们是B类的部分。
Now when class D is derived publicly from class B then the public section of class B becomes public section of class D. Similary, the protected section of class B becomes protected section of class D. Therefore, the public section part of class B can be accessed via object of class D. And since B::a; and B::b; are in public section for members functions of class F, therefore B::a and B::b can be accessed via object of class D. Also note that although after derivation int a; and int b; become members of class D, still compiler is able to distinguish them and considers them a part of class B.
现在当 class D 派生私有来自 class B 然后 class B 的 public 部分变为 private 部分 D类。类似地, class B 的 protected 部分成为 class D $ c的受保护部分$ C>。因此,现在 class B 内的 public 部分无法通过 D类。回想一下,在 B类, B :: a; 和 B :: b; 最初是公共部分的类F 的成员函数,但在 private 派生后,成员 B类即 B :: a 和 B :: b 现在位于 class D 的私有部分。因此, B :: a 和 B :: b 无法通过 D类。另请注意,虽然在派生后 int a; 和 int b; 成为类D的成员,仍然编译器能够区分它们并将它们视为B类的部分。推导后, B类的某些成员的可访问性和规则已经改变。
Now when class D is derived privately from class B then the public section of class B becomes private section of class D. Similary, the protected section of class B becomes protected section of class D. Therefore, now the public section part inside of class B cannot be accessed via object of class D. Recall that in class B, B::a; and B::b; are originally in public section for members functions of class F but after private derivation, the members of class B i.e B::a and B::b are now in private section of class D. Therefore, B::a and B::b cannot be accessed via object of class D. Also note that although after derivation int a; and int b; become members of class D, still compiler is able to distinguish them and considers them a part of class B. After derivation the accessibility and rules of some members of class B have changed.
因为这个问题在某种程度上与效果有关公共,受保护和私有派生,因此为了完整性,请参阅:
Since this question somewhat relates to effect of public, protected and private derivation, therefore for completeness please see:Why can a derived class not access a protected member of its base class through a pointer to base?
这篇关于朋友类对象可以在派生类对象上访问基类私有成员吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!