在C++中理解继承/友元类成员访问

3

来看看这些类:

class Base {
    friend class Pal;
public:
    void pub_mem();
protected:
    int prot_mem;
private:
    int priv_mem;
};

class Sneaky : public Base {
private:
    int j;
};

class Pal {
public:
    int f1(Base b){
        return b.prot_mem;  //OK, Pal is friend class
    }

    int f2(Sneaky s){
        return s.j;  //error: Pal not friend, j is private
    }

    int f3(Sneaky s){
        return s.prot_mem; //ok Pal is friend
    }
}

这里Pal是Base的友元类,而Sneaky继承自Base并被用于Pal中。 现在在调用s.prot_mem的最后一行中,作者给出了它之所以有效的原因是Pal是Base的友元类。但是根据我所读到的内容,我的理解告诉我它应该无论如何都可以工作,因为s派生自Base,prot_mem是Base类的受保护成员,这应该已经可以让Sneaky访问,你能解释一下我哪里错了或者更详细地阐述一下吗?


如果你的问题是关于代码是否应该在没有友元的情况下编译,那么你本可以一开始就不使用友元来发布它。这样会更清晰明了。此外,friend-class 标签对于分类这个问题并没有任何帮助,因为你实际上是在询问没有友元的行为。 - Daniel Daranas
3个回答

2
我的理解告诉我,它应该会工作,因为s是从基类(Base)派生的,并且prot_mem是Base类的受保护成员,该成员应已经可以访问Sneaky。
不,受保护的变量prot_mem只能被派生类成员访问,而不能被第三方类成员像Pal类访问,除非Pal是Base的友元类。

哦,现在我明白了,当我们在另一个类中使用一个对象时,那么任何对 s.member 或 s->member(如果是指针)的操作只能获取“public”成员,对吗? - Jason

1
没有友谊,Pal 只能看到 Sneaky 或 Base 的公共成员。 Base 中的一个成员受到保护并不会对 Pal 有任何好处 - 这只会使 Sneaky 受益。

1
事实上,尽管 Sneaky 可以访问 prot_mem,但您展示的代码不在 Sneaky 中,而是在 Pal 中。如果 Pal 是一个无关的类,则无法访问 Sneaky 中也受保护的 prot_mem。然而,PalBase 的友元类,这使它获得了必要的访问权限。

好的,谢谢。但是当我们将Sneaky对象作为参数传递并调用s.prot_mem时,访问是由Sneaky而不是Pal调用的,不是吗? - Jason
@Jason 访问保护检查代码执行访问是否具有正确的权限。执行对s.prot_mem读取的代码位于哪里?它在类Pal中,因此具有Pal的访问权限。换句话说,访问是由PalSneaky进行调用的。 - Angew is no longer proud of SO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接