11

如果我有两个继承类如下:

class A
{
    ...
}

class B : public A
{
    ...
}

第三类定义为朋友类A:

class C
{
    friend class A;
}

我是否能够从class B(也是 type 的对象A)访问所有成员,class C就好像我首先定义class B了朋友类一样?

4

8 回答 8

21

friendship 既不是继承的也不是传递的。这是两个类之间严格的一对一关系。

class A {
  friend class B;  
  int Aries;
};

class B {
  friend class C;  
  int Taurus;
};

class C {
  int Leo;
  void Capricorn() {
    A a;
    a.Aries = 0;  // this wont work, C is not a friend of A.
                // friendship is not transitive
  }
};

class D : public C {
  void Gemini() {
    B b;
    b.Taurus = 0;  // this wont work, D is not a friend of B.
                   // friendship is not inherited
  }
};    

class E : public B {
  void Scorpio() {
    C c;
    c.Leo = 0; // this wont work either, friendship is not inherited
  }
};

参考:“C++ 编程语言”Bjarne Stroustrup

更多解释(我的):如果friend船不是一对一的,那将是封装的结束。请注意,只有当类声明声明为时,B类才能访问private的成员。无法强制发货。AABfriendBfriendA

现在,如果友谊可以被继承,那么某人只需要继承B就可以访问 的私有成员A,而没有A任何发言权来阻止它。此外,允许friendship 是可传递的会导致其他问题,因为 nowB可以有一个friend C,而谁又可以有一个friend D,一直到Z。所有B, C, D, ...Z现在都可以访问Aprivate成员,这将是一场灾难。

于 2012-12-12T16:40:14.817 回答
4

由于某种原因,每个人都忘记了您可以访问派生自友谊给予者的类的虚拟私有函数。

#include <iostream>

class Friend;
class Parent
{
    friend class Friend;
private:
    virtual void nameYourself() { std::cout << "Parent" << std::endl; }
};

class Child : public Parent
{
private:
    virtual void nameYourself() { std::cout << "Child" << std::endl; }
};

class Friend
{
public:
    void foo(Parent *p) { p->nameYourself(); }
};

int main()
{
    Parent p;
    Child c;
    Friend f;
    f.foo(&p);
    f.foo(&c);
    return 0;
}

运行上述代码的输出是:

Parent
Child

它起作用的原因很棘手,并且与该指针的传递方式有关(查找 vtables)。如果您从函数声明中删除“virtual”关键字,您将失去此能力。

于 2015-07-14T04:16:09.767 回答
2

引用标准 C++11 11.3/10:

友谊既不是遗传的,也不是传递的。

这意味着派生类的朋友和朋友的朋友都不能获得友谊的好处。

于 2012-12-12T16:50:16.580 回答
1

在上面我发现有用的蒙面人答案/代码中添加了一个示例:

class B {
  friend class F;
  friend class E;
  int Taurus;
};

class E : public B {
  int Egg;
};

class F {
    void Foo () {
       B b;
       b.Taurus = 4;  //Works F is friend of B (of course)
       E e;
       e.Taurus = 6; // Works E is derived from B and F is friend of B 
                  // Taurus is private member of B.
       e.Egg = 5; // Does not work, F is friend of Base Class B but not
               // E, so can't access members of the derived class
    }
};
于 2015-10-14T23:36:13.660 回答
0

我认为这取决于。您将可以从 B 的 A 部分(切片部分)访问。如果你定义了 B 自己的函数,我想你不会。

于 2012-12-12T16:28:06.820 回答
0

我不明白您要做什么,但是 B 是 A 的超类。不是对象。B和C之间没有任何继承关系

于 2012-12-12T16:37:54.310 回答
0
  • 否 - 它不是继承的(见下文);如果 B 是 A 的子类并且 C 是 A 的朋友,则 B 无权访问 C 的私有成员,包括继承的成员。
  • 同样,如果 A 是 C 的朋友,或者如果 A 和 C 都是彼此的朋友,这不会让 B 访问 C 的私有成员,包括继承的成员。
  • 此 URL 声明朋友类的子类不继承朋友关联:

    C++朋友继承?

  • 这适用于两个“关联(主类自己的和与主类友好的其他类)”——这里的问题是后一种情况。

于 2012-12-12T16:46:24.967 回答
0

不,您不能C直接调用类方法,但可以通过指针访问它们。A类应该被修改:

class C
{
  void method()
  {
  }
  friend class A;
};

class A
{
protected:
  constexpr static void (C::*f)() = &C::method;
};

class B : public A
{
  B()
  {
    //C().method(); ← This wont work
    (C().*f)(); // ← This works fine
  }
};

访问数据成员和静态数据也很简单

于 2018-03-15T15:39:55.950 回答