Hem*_*rma 12 c++ inheritance private friend
我很惊讶下面的代码编译.
似乎一个与(公共继承)基类成为朋友的类可以访问基类的成员,提供派生类的实例.
如果继承被更改为private
则编译失败.
总之,内部如何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";
}
Run Code Online (Sandbox Code Playgroud)
对象class D
由2个独立部分组成:
part containing members of B
part containing members of D
Run Code Online (Sandbox Code Playgroud)
这就是为什么对象切片的概念在我们做的时候起作用:
D objD;
B objB = objD;
Run Code Online (Sandbox Code Playgroud)
现在,我们可以从内部访问object of class D
的,part containing members of B
通过objB
.编译器记住或可以区分内部的两个部分class D
.所以编译器知道通过什么访问什么.
friend class F;
里面的声明class B
只是说member functions of class F
可以访问private, protected and public
成员class B
.也就是说,对于member functions of class F
所有成员class B
都是public
.
实际上,每个班级里面都有三个部分可访问性:
public
protected
private
Run Code Online (Sandbox Code Playgroud)
所以当我们宣布一些时class B
:
class B
{
public:
int a;
protected:
int b;
public:
int c;
};
Run Code Online (Sandbox Code Playgroud)
然后在类中创建以下3个部分,B
如上所示.
现在,当我们宣布一些class F
是一个friend
的class B
:
class B
{
friend class F;
private:
int a;
protected:
int b;
public:
int c;
};
Run Code Online (Sandbox Code Playgroud)
然后编译器创建如下部分:
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
};
Run Code Online (Sandbox Code Playgroud)
需要注意的是int a;
和int b;
现在公众member functions
的class F
.
现在,当class D
导出publicly
从class B
随后public
部分的class B
成为public
的部分class D
.与之相似,该protected
部分 class B
变成protected
部分class D
.因此,public
部分部分class B
可以通过对象访问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
导出privately
从class B
随后public
部分的class B
成为private
的部分class D
.相似,该protected
部分 class B
成为受保护的部分class D
.因此,现在public
里面的部分部分class B
无法通过对象访问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
派生的效果有关,因此为了完整性,请参阅:
为什么派生类不能通过指向base的指针访问其基类的受保护成员?
D
是一个B
使用公共继承的时候.所以访问b_var
仍然完全合法.
但是,如果您尝试访问d_var
,则会收到错误,因为您似乎意识到友谊本身并未继承.
继承总是使基类的所有成员都是派生的成员.访问说明符仅影响标识符可见的位置.这就是为什么非法访问私有成员会产生不同的错误来访问不存在的标识符.