1

如果是这样,在什么情况下这可能有用?

或者(我想是这种情况),为什么它绝对没用?(还有什么其他方法基本上涵盖了这种友谊所提供的能力,但以一种更安全、更少泄露的方式?)

我当时几乎认为我需要这样的东西。最后我追求了一个完全不同的设计,使所有的类成员都是静态的。不过我还是很好奇。

4

3 回答 3

3

有没有办法让所有派生类成为彼此的朋友?

该语言不提供任何机制来在基类中指定类似的内容。您必须在从基类继承的每个类中提供友元声明。

我无法提出更积极的建议,因为我不知道您要解决的问题。

在评论中,你说:

就我而言,我需要访问同级方法,所以如果BC派生自A,我需要调用B::foo()from C::foo()。在我的情况下,这些类封装了不同的算法(因此想到了策略模式......)但有时一种算法会使用另一种算法的大部分。C然而,从派生似乎并不正确B,因为C与 并没有真正的“is-a”关系B

如果C与 没有“is-a”关系B,但C::foo()不知何故需要调用B::foo(),这向我表明B::foo()只能使用B和共有的数据C。在这种情况下,应该可以将代码分解为非成员函数,然后从B::foo()and中使用它C::foo()

将依赖项更改为:

B::foo()
   ^
   |
C::foo()

 <some namespace>::foo()
          ^
          |
  +-------+---------+
  |                 |
B::foo()          C::foo()
于 2015-07-17T17:16:01.027 回答
3

C++ 只给你两种命名朋友的方法:

friend class C; // a specific class

template <typename T>
friend class S; // friend the class template S

没有办法在其中插入元函数,假设看起来像这样:

template <typename T>
friend enable_if_t<std::is_base_of<Base, T>::value, T>;

但我想如果你对可怕的黑客持开放态度(这个短语应该被解释为永远不要这样做,请上帝不,但它至少有点有趣),你可以简单地将所有派生类型实现为某个模板的显式特化。

struct Base { ... };

template <typename > class Derived;

struct A_tag { };

template <>
class Derived<A_tag> : Base {
    template <typename T>
    friend class Derived;

    ...
};

using A = Derived<A_tag>;

如果我们对 , 等做类似的事情BC那么A,BC相互都是朋友 - 因为在幕后他们真的是Derived<A_tag>, Derived<B_tag>,Derived<C_tag>因此朋友类模板语句涵盖了所有这些。

于 2015-07-17T17:45:37.403 回答
2

friend完全是,但您可以使用密码模式的某些变体来限制访问

如果您在基类中创建受保护的内部 Passkey 类。然后,任何派生类都可以通过要求 Passkey 作为参数来限制对兄弟的访问:

class A {
protected:
  class Passkey {};
};

class B : public A {
public:
  void someProtectedFunction(Passkey) {};
};

class C : public A {
public:
  void somePublicFunction() {
    B b;
    b.someProtectedFunction(A::Passkey{});
  }
};

int main() {
  C c;
  c.somePublicFunction();

  B b;
  //b.someProtectedFunction(A::Passkey{});  // error: `class A::Passkey` is protected
}
于 2015-07-17T17:51:54.913 回答