使用非抽象类作为基础

时间:2009-11-13 17:27:12

标签: c++

我需要完成其他开发人员的工作,但问题是他以不同的方式开始...... 所以现在我发现在使用现有代码的情况下,他选择继承一个非抽象类(非常大的类,没有任何虚函数)已经实现了一堆接口或者忽略了那些代码(这应该不是很多工作)并编写另一个实现我需要的接口的类。

有哪些优点和缺点可以帮助我选择更好的方法。

P.S。请注意,我没有太多经验

非常感谢

5 个答案:

答案 0 :(得分:3)

虽然再次从头开始写它是非常诱人的,但不要这样做!现有的代码可能很难看,但它看起来确实有效。由于班级很大,我认为它背后也有相当多的历史。对于一些你可能想不到的非常模糊的案例,它可能有解决方案。我建议的是,如果可能的话,首先要与开发该课程的人交谈,了解它是如何工作的,然后从中推导出来(当然是虚构化它的析构函数)并完成你的工作。然后当时间允许时,慢慢地将类的部分重构为更小的更易于管理的类。此外,不要忘记在开始之前编写一个好的单元测试器,以便您可以根据现有类的行为验证新行为。还有一点,从非抽象基类继承是没有错的,只要它有意义并且基类析构函数是虚拟的。

答案 1 :(得分:2)

如果其他开发人员编写了没有虚函数的基类,则不需要重写这些函数,并且在非抽象基类中定义它们是正确的。

如果这些函数定义了所有子类所需的功能,那么删除基类将是错误的,因为您需要在每个子类中单独实现这些函数。

我看到很多开发人员在过去几年中都采用'界面疯狂',但是基类仍然在接口上提供功能 - 提供所有子类通用的具体实现。摆脱基类并在每个子类中单独实现这些函数是错误的。

但是,如果子类继承了他们不需要的功能,或者需要单独的实现,那么Base类就是一个错误,接口似乎是在子类之间划分功能的更好选择。 / p>

尽管如此,我同意Naveen认为它可能不值得为你提供额外的工作,这看起来很简单,但如果这是一个有很多继承人的大班,那么它可能会变成一场噩梦。在软件工程中,您必须处理另一个开发人员的代码,这些代码可能以不同的方式实现。如果你重新实现它,你将成为一个非常低效的开发人员。我说你用你所得到的东西,按时完成项目。

答案 2 :(得分:1)

你想从基类中使用什么,或者你最终会覆盖所有内容?

它是否定义了您想要用于“is-a”关系的某种类型? (例如,基类是“动物”,你想制作“cat”,但如果它没有向其界面添加任何行为,那似乎不太可能)

您需要在其他接口中使用基类吗? (比如有人通过引用/指向基类的对象传递对象)

如果没有,我会说自己继承该类没有优势继续实现接口。

答案 3 :(得分:1)

  

有哪些优点和缺点可以帮助我选择更好的方法。

从没有虚函数的类派生是合法的,但这并不是一个好主意。当您从具有虚拟函数的类派生时,您经常通过指针使用该类(例如,从Derived继承的类Base通常通过{{1}进行操作}} S)。当您不使用虚拟功能时,这不起作用。此外,如果你有一个指向基类的指针,Base* - 它可能导致内存泄漏。

然而,听起来更像是这些类没有通过指针到基础使用。相反,基类只是用于获得大量内置功能,尽管这些类在正常意义上并不相关。 Inversion of control(和has-a relationships)是一种比较常见的方法(将基类的功能分解为多个接口 - 纯虚基类 - 然后拥有当前的对象派生自基类,而不是那些接口的成员变量。)

至少,您需要将大型基类拆分为明确定义的较小的类并使用它们(如mixins),这听起来像是您的第二个选择。

但是,这并不意味着一次性重写所有使用blob基类的其他代码。这是一项艰巨的任务,你可能会犯小错字和类似的错误。相反,请自己购买Working Effectively With Legacy CodeLarge-Scale C++ Software Design的副本,并逐步完成工作。

答案 4 :(得分:0)

从你的问题来看,问题是什么并不太清楚 - 看标题(使用非抽象类作为基础)我可以告诉你使用抽象类(非纯虚拟 - 当你谈论C ++中的接口时我假设是纯虚拟抽象类)因为只有在子类之间可以共享的共同功能时才有意义 - 这意味着许多类扩展了继承公共实现的相同抽象类。如果情况并非如此(并且您非常有信心它永远不会发生)那么使用抽象类是没有意义的。

如果你能够以一种导致(甚至潜在的)代码重用的方式提取你的大类中的一些功能,那么它就有意义了 - 否则我不会明白这一点。