【问题标题】:Is it bad practice for a child object to have a pointer to its parent?子对象有一个指向其父对象的指针是不好的做法吗?
【发布时间】:2010-09-16 06:00:13
【问题描述】:

在 C++ 应用程序中,假设我有一个窗口类,它有多个控件类实例。如果我的窗口想要通知控件它已被点击,我可以使用:

control[n]->onClick();

现在假设控件需要知道它的父窗口的大小,或者其他一些信息。为此,我正在考虑为控件提供一个指向自身(this)的指针作为其构造函数的参数。然后我会从控件的 onClick() 方法中进行这样的调用:

Size windowsize = parent->getSize();

这会被认为是不好的做法,还是以任何其他方式与面向对象编程的价值观相矛盾?如果是这样,他会以什么“正确”的方式做到这一点?

作为一个附带问题,拥有 Class 或 Class* 的向量会更好吗?是否值得为速度增益增加复杂性? (对向量的更改很少)。

【问题讨论】:

  • @Martin:你有什么问题...?没有太多的抱怨没有解释......
  • @Tony:Mark Cidade 更正了标题,该标题最初与@Martin 评论中的引用完全一致。我认为抱怨是标题有点模糊。

标签: c++ oop


【解决方案1】:

您可以将控件层次结构视为树状图数据结构;当您以这种方式对其进行可视化时,控件具有指向其父级的指针是非常合理的。

至于是否应该将对象或指向对象的指针存储在向量中,这取决于。您通常应该更喜欢存储对象,但很多时候您不能这样做,或者这样做是不切实际的。例如,如果您需要利用多态性并存储所有从公共基类派生的不同类型的事物,则需要使用指针。

如果您确实存储指针,请确保使用某种智能指针或指针容器;否则,异常安全是一个打击。

【讨论】:

    【解决方案2】:

    没关系。这是 UI 框架中的常见模式。例如,.NET Windows Forms Control 类具有用于指定父级 (http://msdn.microsoft.com/en-us/library/wawy06xc.aspx) 的构造函数。

    【讨论】:

      【解决方案3】:

      事实上,GOF 复合设计模式基于显式父引用。

      显式父引用。 维护来自孩子的引用 组件到它们的父级可以 简化遍历和管理 的复合结构。父母 参考简化了向上移动 结构和删除组件。 家长参考也有助于支持 责任链 (223) 模式。 定义 父引用在组件中 班级。 Leaf 和 Composite 类可以 继承引用和 管理它的操作。

      对于父引用,这是必不可少的 保持不变的所有 复合的孩子有他们的 父组合反过来具有 他们像孩子一样。最简单的方法 确保这是更改组件的 仅当它被添加或 从复合材料中删除。如果这可以 在添加和执行一次 移除 Composite 的操作 类,那么它可以被所有人继承 子类和不变量将 自动维护。

      因此,我想,这样的设计有一个明确的地方,取决于实际的需求和上下文。

      【讨论】:

        【解决方案4】:

        不,完全没问题。唯一的问题是它增加了实例之间的耦合程度。此外,如果您按照上面的建议考虑使用智能指针,请确保引用父级“弱”。假设您的窗口树不是太深,您可以考虑从已知的顶部窗口开始确定父窗口。

        【讨论】:

          【解决方案5】:

          没关系。但是,请确保您需要它,因为在孩子的父母可以更改的情况下,它会使您的代码复杂化。检查孩子为什么需要知道其父母是谁,并考虑成本和替代方案。您的方案的一个示例替代方案是:当父窗口调整大小时,可以从上到下调整大小,它可以通过迭代和调用方法或设置属性来告诉其子窗口调整大小。当孩子需要调整大小时(例如可以根据其中的数据增长的文本框),它可以向任何收听的人提出一个事件,说它调整了大小,并且父母可以收听该事件。

          【讨论】:

            【解决方案6】:

            如果您需要这样做,请考虑将父级作为const* 传递。

            【讨论】:

              【解决方案7】:

              还不错。例如,在 Qt 小部件中,每个小部件都有其指向父级的指针,即使不使用 const*

              顺便说一句:这有点令人困惑,因为你说“父母”人们可能会被层次结构父母误解。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-01-18
                • 1970-01-01
                • 2011-12-19
                • 2020-12-11
                • 2023-02-09
                • 2021-10-28
                • 2011-05-17
                相关资源
                最近更新 更多