朋友类对象可以在派生类对象上访问基类私有成员吗?

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)

sam*_*rkn 6

对象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是一个friendclass 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 functionsclass F.

现在,当class D导出publiclyclass 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::aB::b可通过的对象进行访问class D.还要注意的是,虽然派生之后int a;int b;成为会员class D,依然编译器能够区分它们,并认为他们part of class B.

现在,当class D导出privatelyclass 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 BB::aB::b目前在私人部分class D.因此,B::aB::b 不能被通过的对象进行访问class D.还要注意的是,虽然派生之后int a;int b;成为会员class D,依然编译器能够区分它们,并认为他们part of class B.在推导之后,一些成员的可访问性和规则class B已经改变.

由于这个问题在某种程度上与public, protected and private派生的效果有关,因此为了完整性,请参阅: 为什么派生类不能通过指向base的指针访问其基类的受保护成员?


Sto*_*ica 5

D是一个B使用公共继承的时候.所以访问b_var仍然完全合法.
但是,如果您尝试访问d_var,则会收到错误,因为您似乎意识到友谊本身并未继承.

继承总是使基类的所有成员都是派生的成员.访问说明符仅影响标识符可见的位置.这就是为什么非法访问私有成员会产生不同的错误来访问不存在的标识符.

  • @GillBates,继承总是使基数的所有成员都是派生的成员.访问说明符仅影响标识符可见的位置.这就是为什么非法访问私有成员会产生不同的错误来访问不存在的标识符. (2认同)