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

Is there a way to make all derived classes friends of one another?

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

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

当时我几乎认为我需要这样的东西。我最终采用了完全不同的设计,使所有 class 成员都静态化。不过我还是很好奇。

Is there a way to make all derived classes friends of one another?

该语言不提供任何机制来在基 class 中指定类似的东西。您必须在从基础 class.

继承的每个 class 中提供友元声明

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

在评论中,您说:

In my case, I needed to access sibling methods, so if B and C derive from A, I needed to call B::foo() from C::foo(). In my case these classes encapsulate different algorithms (so the Strategy pattern comes to mind...) but sometimes one algorithm would use a substantial portion of another algorithm. Yet, it didn't seem correct to derive C from B, because C doesn't really have an "is-a" relationship with B.

如果 CB 没有 "is-a" 关系,但 C::foo() 以某种方式需要调用 B::foo(),这表明我B::foo() 只能使用 BC 共有的数据。在那种情况下,应该可以将代码分解为非成员函数,然后从 B::foo()C::foo().

中使用它

更改依赖于:

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

 <some namespace>::foo()
          ^
          |
  +-------+---------+
  |                 |
B::foo()          C::foo()

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等做类似的事情,那么ABC都是朋友-因为在引擎盖下它们实际上是 Derived<A_tag>Derived<B_tag>Derived<C_tag>,因此 friend class 模板语句涵盖了所有这些。

不完全是 friend,但您可以使用 Passkey pattern

的某些变体来限制访问

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

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
}