【问题标题】:how will Contained class call member function of containing class - Composition in C++包含类如何调用包含类的成员函数 - C++ 中的组合
【发布时间】:2011-04-12 04:33:01
【问题描述】:

这是从 C++ 角度来看的一般设计问题。我有一个容器类,其中包含 2 个其他类的对象。

从容器类中,我们可以调用包含的类对象的方法,“因为我们拥有包含的类对象的句柄”,例如objContainedClass1->SomeMthod();

但我想知道包含的类对象(objContainedClass1)如何访问容器类的方法。

我可以想到以下几种方式:

  1. 容器类对象将指向自身的指针(this 指针)传递给包含的类构造函数。使用这个指针,被包含的类可以访问容器类的方法。

  2. 将容器类中的一些函数设为静态。

还有什么实现这一点的想法吗?

谢谢

【问题讨论】:

    标签: c++ oop ooad


    【解决方案1】:

    不要,通常一个类必须知道它的容器是不好的设计。通常这意味着你违反了单一责任原则。

    【讨论】:

    • 我真的不明白双向关联与单一责任原则有什么关系。我可以想到许多双向关联即使不是强制性的也很有用的情况。例如,在树结构中(参见 Composite),在节点中引用父节点通常很有用。
    • 这取决于具体情况。在图中,了解其他节点并不是什么大问题。然而,在大多数其他情况下,这是一个坏主意。套接字不应该知道它们所在的 FD_SET,如果你的实现知道,那是因为你的套接字做的不止一件事,也就是违反 SRP。所以这不是一个自动的不不,而是十分之九的事情是不正确的。大多数时候,当我看到它时,容器就是一个容器,并且在做其他事情,它应该只包含另一个对等点。
    • 我希望我可以删除我的反对票,因为您的评论现在增加了我认为您的答案中缺少的细微差别,但它不再可能:(。
    【解决方案2】:

    两种方式都可以用于不同的目的。如果你只需要调用静态方法,#2 就可以了。但是如果你需要访问容器类的实例方法,你需要有容器类指针,所以#1是方法。

    如果您需要通用解决方案,请实施观察者模式。在这种情况下,包含的类对容器一无所知,它只是在必要时引发事件。

    【讨论】:

    • 为了实现观察者模式,特别是在引发事件时,不包含对象需要调用容器的类函数吗? IE。我们回到原来的问题。
    【解决方案3】:

    有许多糟糕的选择。

    您可以将包含的类作为容器类的一部分,如果它们不在容器类之外使用的话。

    您可以让容器成为所包含类的朋友(糟糕)。

    您可以将引用或 boost::shared_ptr 传递给容器,而不是原始指针。最好的方法取决于每个人的寿命。如果可以,请避免使用原始指针。

    我实际上会尝试做的是隔离包含的对象需要使用的容器方法的接口(例如IContainerCallback),并将其用作两者之间的链接。因此,包含的对象只是通过与容器的实现分离的接口类间接引用容器。

    【讨论】:

      【解决方案4】:
      • 将容器类中的一些函数设为静态。

      这就是所谓的“再见OOP!”选项,我尽可能避免使用它。

      • 容器类对象将指向自身的指针(this 指针)传递给包含的类构造函数。使用这个指针,被包含的类可以访问容器类的方法。

      前提是包含类实现了一个接口,并且包含的​​类只知道接口,我个人看不出有什么问题。事实上,这就是我自己所做的。显然,一个人必须意识到这种方法的陷阱,例如,当包含的对象在后者销毁期间(或容器处于中间状态的任何其他时刻)调用容器的方法。

      为了进一步将包含的类与包含的类分离,也可以使用事件或消息。包含的对象不知道它们包含在哪里,而是发送消息。包含对象在创建包含对象时将自己注册为来自它们的消息的接收者。该技术允许使对象在字面上独立,但需要 (1) 一些消息传递框架,(2) 由于 C++ 的静态特性,实现起来相当复杂, (3) 还需要额外级别的文档,因为类的接口现在包括消息传递。

      否则,请三思为什么包含的对象需要调用容器的方法。是不是您需要将容器中的一些通用功能拆分为第三类?如果包含的对象确实是活动对象并且是系统中事件的逻辑源,那么您可能确实需要一些基本的事件/消息传递系统来允许容器有效地轮询/监视包含对象中的状态变化。

      【讨论】:

        【解决方案5】:

        不要。容器类的职责是包含事物,仅此而已。如果您需要容器类根据其中包含的内容执行操作,请让第三个对象执行这些操作。例如,我假设您正在根据类的内容重新排列或以其他方式修改类的集合。不要尝试在包含的类中执行此操作,而是在使用容器作为依赖项的类中执行此操作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-21
          相关资源
          最近更新 更多