友谊的替代品?

时间:2011-10-28 19:06:30

标签: c++ encapsulation friend access-control

在以下情况中,友谊是否有其他选择?

我有一个代表UI窗口的Window类。此外,作为单例实现的WindowManager类管理应用程序中的所有窗口对象(呈现UI,调度事件等)。

WindowManager将具有一个公共接口,该接口仅包含其单例实例化方法和用于呈现UI和分派UI事件的函数。

我还希望Window个对象在构造期间注册WindowManager并在销毁期间取消注册。 WindowManager::registerWindowManager::deregister方法将是私有或受保护的,因为我不希望客户端(Window个对象除外)能够使用此接口。

在这种情况下,是否有一种方法可以避免WindowWindowManager之间的友谊?也许是一种完全不同的方式来实现类似的结果?

5 个答案:

答案 0 :(得分:4)

是的,但友谊是最好的解决方案,因为它专为这种情况而设计。

另一种方法是让Window成为WindowManager的成员(注意,这需要新的C ++ 11辅助功能规则)。或者它来自WindowManager的成员。或者它来自WindowManager本身。

您还可以在Window中放置一个私有类型,使Window中嵌套的密钥类型只能从该私有类型构造,并且需要将该密钥类型的实例传递给{{ 1}}。这应该适用于C ++ 11之前的编译器。

当然,任何方法都可以使用足够的投射来绕过。

答案 1 :(得分:2)

在这里使用Friend似乎是合适的。您想在两个类之间指出故意强耦合,这可以通过朋友恰当地表明。

更具体地说,一个类需要访问另一个类的内部,并且您不希望使用公共访问说明符授予每个人访问权限。

经验法则:公众太弱,私人太强,你需要某种形式的选择访问:受保护或朋友。

使用Friend发货是这里的最佳解决方案。

答案 2 :(得分:2)

使用嵌套类。

WindowManager {
  private:
    static void construct();
    static void destruct();
  public:
    class InternalWindow { // can access WindowManager's private members (no scoping needed)
      InternalWindow() { construct(); }
      ~InternalWindow() { desstruct(); }
    };
};

typedef WindowManager::InternalWindow Window; // to make scoping easier

答案 3 :(得分:2)

另一个解决方案(不一定更好:])是将窗口注册放到a separate component - 让我们说WindowRegister。 WindowRegister可以有一个公共接口进行注册,也可以是WindowManager的私有成员。

problem with friendship is that it is not inherited(我的爷爷的朋友不需要我的朋友) - 并且Window或WindowManger很可能是多态的。

此致

答案 4 :(得分:1)

还有其他几种选择。例如:

  • 您可以使用指针数学,汇编代码和有关内存中类的布局的知识来在运行时调用私有方法。然而,这不是很便携。
  • 您可以将该方法设置为public,但要求它使用一个存储在Window类中的私钥加密签名的参数,从而阻止其他类实际调用该方法并让它执行任何操作。
  • 您可以使该方法受到保护,并使另一方继承。
  • 你可以创建一个它们都继承的公共超类,并使用它们的受保护方法在它们之间进行通信。
  • 您可以使用少用的“敌人”关键字来允许他们运行彼此的私有方法,但只有当他们拥有勒索其他类的勒索材料时。 (好吧,这不是一个真正的语言功能,但它应该是。)

或者你可以让他们成为朋友。这比任何其他选项更容易和更安全,以及为什么朋友存在。