【问题标题】:Is there a way to make all derived classes friends of one another?有没有办法让所有派生类成为彼此的朋友?
【发布时间】:2015-07-17 17:05:14
【问题描述】:

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

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

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

【问题讨论】:

  • 在基类中提供受保护的方法可以避免有这么多朋友。
  • 缺少一个关键要素: 他们在访问什么?
  • @Quentin - 就我而言,我需要访问同级方法,所以如果BC 派生自A,我需要从C::foo() 调用B::foo()。在我的例子中,这些类封装了不同的算法(因此想到了策略模式......)但有时一种算法会使用另一种算法的大部分。然而,从B 派生C 似乎并不正确,因为CB 并没有真正的“is-a”关系。

标签: c++ derived-class c++03 friend-class


【解决方案1】:

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

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

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

在评论中,你说:

在我的例子中,我需要访问同级方法,所以如果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()

【讨论】:

    【解决方案2】:

    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&lt;A_tag&gt;Derived&lt;B_tag&gt;Derived&lt;C_tag&gt;,因此朋友类模板语句涵盖了所有这些。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-24
        • 1970-01-01
        • 2010-11-22
        • 1970-01-01
        • 2014-02-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多