看来,类(公开继承)的基类可以访问派生类的实例的基类的成员.
如果继承更改为私有,则编译失败.
简而言之,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"; }
解决方法
part containing members of B part containing members of D
为什么对象切片的概念在我们做的时候起作用:
D objD; B objB = objD;
现在我们可以通过objB从D类的内部对象访问包含B的成员的部分.编译器记住或可以区分类D内的两个部分.所以编译器知道正在通过什么访问什么.
声明朋友类F;在B类内部简单地告诉F类的成员函数可以访问类B的私有,受保护和公共成员.也就是说,对于类F的成员函数,B类的所有成员都是public.
其实每个班里面都有三段w.r.t可访问性:
public protected private
所以当我们声明一些B类:
class B { public: int a; protected: int b; public: int c; };
那么如上所示,在B类中创建以下3个部分.
现在我们宣布一些F级成为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和int b;现在公开为F类的成员职能
现在当D类从B类公开派生时,B类的公共部分成为D类的公共部分.Similary,B类的被保护部分成为D类的保护部分.因此,B类的公共部分部分可以通过D类的对象访问.由于B :: a;和B :: b;在F类的成员函数的公共部分中,因此可以通过类D的对象访问B :: a和B :: b.另请注意,虽然在导出后,int a;和int b;成为D类的成员,仍然编译器能够区分它们并将它们视为B类的一部分.
现在,当D类从B类私有派生时,B类的公共部分成为D类的私有部分.Similary,B类的受保护部分成为D类的保护部分.因此,现在B类中的公共部分不能通过类D的对象访问.回想一下,在B类中,B :: a;和B :: b;最初在公共部分用于F类的成员函数,但是在私有派生之后,B类的成员即B :: a和B :: b现在是类D的私有部分.因此,B :: a和B :: b不能通过类D的对象访问.另请注意,虽然在派生后int a;和int b;成为D类的成员,仍然编译器能够区分它们并将其视为B类的一部分.派生后,B类的某些成员的可访问性和规则已更改.
由于这个问题有点与公共,受保护和私人派生的影响有关,所以为了完整性,请参见:
Why can a derived class not access a protected member of its base class through a pointer to base?