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

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

本文关键字:朋友 派生 有没有      更新时间:2023-10-16

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

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

我几乎认为我需要这样一个东西。最后我采用了一种完全不同的设计,让所有的类成员都是静态的。我还是很好奇

是否有办法使所有的派生类彼此为友?

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

我不知道你们要解决的问题是什么,所以我不能给出更积极的建议。

在评论中,你说:

在我的例子中,我需要访问兄弟方法,所以如果BC派生自A,我需要从C::foo()调用B::foo()。在我的例子中,这些类封装了不同的算法(所以我想到了策略模式……),但有时一个算法会使用另一个算法的大量部分。然而,从B推导出C似乎是不正确的,因为CB并没有真正的"is-a"关系。

如果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>;

如果我们对B, C等做类似的事情,那么A, BC相互都是朋友-因为在底层它们实际上是Derived<A_tag>, Derived<B_tag>Derived<C_tag>,因此朋友类模板语句涵盖了所有它们。

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

如果在基类中创建受保护的内部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
}