来自几个类的虚拟事件处理程序:多重继承或组合?

时间:2012-09-06 08:42:12

标签: c++ oop event-handling multiple-inheritance composition

我的团队编写了几个C ++类,它们通过纯虚拟回调实现事件处理 - 例如,当从另一个进程接收消息时,处理IPC消息传递的基类调用它自己的纯虚函数,以及派生类句柄覆盖该函数的事件。基类知道事件已经发生;派生类知道如何处理它。

我现在想要将这些基类提供的功能组合在更高级别的类中,例如当消息从另一个进程到达时,我的新类可以使用类似的事件通过其网络连接转发它 - 驱动网络课程。看起来我有两个选择:

  • (1)组合:从每个事件处理基类派生类,并将这些派生类的对象作为成员添加到我的新类中,或者:

  • (2)多重继承:使我的新类成为所有事件处理基类的派生类。

我已经尝试了(1)和(2),我对我的实现都不满意。

还有一个额外的复杂问题:一些基类是使用初始化和关闭方法编写的,而不是使用构造函数和析构函数,当然这些方法在每个类中都有相同的名称。因此,多重继承会导致函数名称歧义。可以通过using声明和/或明确的范围确定,但不是我见过的最易于维护的东西。

即使没有这个问题,使用多重继承并覆盖来自几个基类中的每一个的每个纯虚函数,都会使我的新类非常大,接近“上帝对象”的性质。随着需求的变化(读作:“随着要求的增加”),这不能很好地扩展。

另一方面,使用单独的派生类并将它们添加为我的新类的成员意味着我必须在每个派生类上编写许多方法来在它们之间交换信息。这听起来非常像“吸气者和制定者” - 并不是那么糟糕,但是有很多“从这个类中获取这些信息并将其交给这一个”,这对它有一种低效的感觉 - 许多额外的方法,很多额外的读取和写入,并且类必须知道很多关于彼此的逻辑,这感觉是错误的。我认为一个成熟的发布和订阅模型会有点矫枉过正,但我​​还没有找到一个简单的替代方案。

如果我使用合成,还会有很多重复数据。例如,如果我的类的状态取决于它的网络连接是否已启动并运行,那么我必须在受此影响的每个类中都有一个状态标志,或者让每个类在每次决定需要时查询网络类的状态。做成。如果我只有一个乘法继承的类,我可以使用一个标志,我的类中的任何代码都可以访问。

那么,多重继承,组合还是其他完全不同的东西?关于如何最好地处理这类事情,是否有一般的经验法则?

2 个答案:

答案 0 :(得分:1)

从你的描述中我认为你已经选择了一种“模板方法”风格的方法,其中基础确实有效,然后调用派生类实现的纯虚拟而不是“回调接口”方法,这几乎是一样的除了纯虚方法在一个完全独立的接口上,它作为构造函数的参数传入“base”。我个人更喜欢后者,因为当把对象插在一起并构建更高级别的对象时,我发现它更加灵活。

我倾向于使用组合类来实现组合对象所需的回调接口,然后在更高级别以类似的方式再次组合。

然后,您可以通过让组合对象实现回调接口并将它们传递给构造函数中的“组合”对象来决定是否合适。或者您可以在其自己的对象中实现回调接口,可能更简单,您的编写对象实现的更精确的回调接口,并组成“基础对象”和“回调实现对象”......

就个人而言,我不会选择“抽象事件处理”界面,因为我更喜欢我的代码明确而清晰,即使这会导致它稍微不那么通用。

答案 1 :(得分:0)

我并不完全清楚你的新课程想要实现什么,但听起来你实际上必须为所有这些抽象事件类提供新的实现。

就个人而言,我会喜欢作曲。多重继承很快就会成为一场噩梦,特别是当事情必须改变时,组合会保持现有的关注点分离。

您声明每个派生对象都必须与网络类通信,但您可以尝试将此减少到最小。例如,每个派生的事件对象都纯粹负责将事件信息打包成某种通用数据包,然后将该数据包传递给网络类以进行发送的内容?

如果不确切地知道你的新课程在做什么,很难评论,或者建议更好的模式,但是我的代码越多,我就越能学会赞同旧格言“赞成作文而不是继承”