设计:回调到父类


13

在使用子对象对对象进行建模时,通常通过合成将子对象包括在内,作为父类的成员。但是有时候孩子需要告诉父母一些事情,他们需要调用父母的函数。使用C ++如何做到这一点?一些选项是:

  1. 使父类成为全局类,因此子对象将能够调用父对象的成员函数。

  2. 将父对象作为指针或引用注入到每个子对象中。然后,当子项需要告诉父对象某些内容时,它总是可以这样做,因为它具有可以使用的成员变量。

还有什么其他方法可以做到这一点?这种事情是否有通用的设计模式或名称?

请注意,我对C ++中的想法和解决方案感兴趣,因为在其他面向对象的语言中,细节将有所不同。例如,上面的第2点提到了“指针或引用”,并且两者都只能在C ++中使用。C ++具有其他语言没有的语言功能,因此解决该问题的方法的实现可能会合并这些语言功能,从而使该解决方案与某人使用另一种语言可能提出的解决方案有所不同。


你可以添加一个例子吗?这是您问题的有效示例吗?您有一个带有订单项(子项)的订单对象(=父项),并且想在更改订单项数量时更新订单总额吗?还是在想一些完全不同的东西?
k3b 2012年

@ k3b是的,这是一个有效的示例。孩子中的某些信息已更改,要求父母做某事。
sashang 2012年

只需向每个子类添加一些构造函数参数和引用数据成员。
tp1 2012年

孩子是否需要了解父母的全部知识,还是简单的delegate就足够了?
Julien Guertault

Answers:


16

首先,这可能是代码的味道。对父母/孩子使用合成的要点是父母知道孩子,反之亦然。特别是如果该关系更多地是“包含”而不是“组成”。

对父级的引用是可能的,并且在C ++中相当普遍。在其他语言中,功能对象或事件通常用于允许孩子传达外界可能想知道的事情。这是一种常见的发布-订阅模式。我怀疑哪个更习惯,取决于您使用的C ++版本和代码库的标准。


在我的情况下,这是一种代码气味。好答案。
Martin Pfeffer

3

正如其他人指出的那样,将父对象作为指针或引用注入的基本思想是原则上的方法。

这有一个缺点:在父级和子级之间存在循环依赖关系。如果要避免这种情况,请定义IParent您的父级继承自其的抽象基类(接口)。IParent应该包含方法作为孩子要调用的虚拟函数。然后,注入父对象作为对的引用IParent。因为现在您可以用模拟对象轻松替换父对象,这使得对子对象的单元测试变得容易得多。

如果您的孩子只需要调用父对象的一个​​函数,则一个完整的IParent类可能会过大。在这种情况下,将指向成员函数的指针注入子对象或封装该成员函数的函子对象就足够了。


2

您可以做的是按组成在子类中保留对父级的引用。这样,孩子就可以知道其父并且可以在其上调用公共方法。

因此,我将选择选项2。但是,您必须要小心,当从父级中删除子级时,您需要删除对子级中对父级的引用,并将其指向null(如果有,则指向新的父级。一)。或者,您可以根据上下文简单地删除子对象。


1

向他们传递对父代的引用或指针。您可以使他们成为父母的朋友,或将被调用的方法公开。如果您不想执行上述任何一项操作,则可以向他们传递一个“ bridge”对象,该对象将父方法的一个公开给公众,它本身是父方法的私有嵌套类(因此它可以访问每个父方法) )。但是,在许多情况下,这可能有点太复杂。


1

2)将父对象作为指针或引用注入到每个子对象中。然后,当子项需要告诉父对象某些内容时,它总是可以这样做,因为它具有可以使用的成员变量。

是一个完全可行的选择。所有现代语言都有一个功能,可以用来指代另一种语言。


1

有一种类似的方法,只是略有不同,但具有一些优点:

假设父级A包含组件C。

在组件C中,声明InterfaceC并保留对其的引用。这是组件与外界的接口。

父级A实现InterfaceC,并在组件C中设置其引用。组件C将父级A视为InterfaceC。

这个想法是:组件使用其接口与外界对话。

与直接设置父项相比,使用它的优点是:

说组件做了一些事情,它需要通知父对象。它调用接口。以后,您决定要更改父级。该组件根本不在乎,您也不会对其进行任何更改。

稍后再说,您想通知一个事件许多对象。您只需创建一个InterfaceC列表并为其添加引用。

缺点:父类最终将实现许多接口(尽管我认为这是一个优势,因为通过查看类声明,我立即知道是谁在与之交谈)


0

请注意,这是C#特有的。我不知道c ++是否有类似的东西。

如果您的GUI表单带有按钮,那么通常使用Event-Subscribtion(也称为Observer_patternPublish-subscribe模式)使用另一种方法。

通常,按钮不知道其所在的具体形式。取而代之的是,该按钮触发或发布一个事件,并且表单收到订阅的通知并可以做出相应的反应。

除了gui-s之外,该机制还可用于每个亲子关系

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.