更新:我在这里问了一个更狭窄的问题。
在Modern C++ DesignC++
的第 6-7 页上,Andrei Alexandrescu 对两种语言特性(多重继承和模板)在构建灵活设计方面的优缺点进行了非常基本的讨论。他总结道:
现在将多重继承的缺点列表与模板的缺点列表进行比较。有趣的是,多重继承和模板促进了互补的权衡。多重继承机制稀缺;模板具有丰富的机制。多重继承会丢失模板中丰富的类型信息。模板的专门化无法扩展,但多重继承可以很好地扩展。您只能为模板成员函数提供一个默认值,但您可以编写无限数量的基类。
我能感觉到安德烈在这里所说的非常重要,但如果没有任何例子来说明要点,我无法真正理解所说的内容。这个问题要求提供简单的例子来说明这些观点(请继续阅读)。
为了使问题更具体,我想请您关注多重继承的弱点。这就是安德烈对他们的评价(方括号中的文字是我对上下文的理解):
在这样的设置中[即多重继承],[构建一个灵活的,]用户将通过继承一些类和两个类
SmartPtr
来构建一个多线程、引用计数的智能指针类:和。任何有经验的类设计师都知道,这种幼稚的设计是行不通的。BaseSmartPtr
MultiThreaded
RefCounted
分析多重继承无法创建灵活设计的原因为达成合理的解决方案提供了有趣的想法。使用多重继承组装单独的特征的问题如下:
- 力学。没有样板代码可以以受控方式组装继承的组件。唯一结合 BaseSmartPtr、MultiThreaded 和 RefCounted 的工具是一种称为多重继承的语言机制。该语言在组合基类时应用了简单的叠加,并建立了一组访问其成员的简单规则。除了最简单的情况外,这是不可接受的。大多数时候,您需要仔细协调继承类的工作以获得所需的行为。
- 类型信息。基类没有足够的类型信息来执行它们的任务。例如,假设您尝试通过从 DeepCopy 基类派生来为您的智能指针类实现深度复制。但是 DeepCopy 会有什么接口呢?它必须创建它还不知道的类型的对象。
- 状态操纵。使用基类实现的各种行为方面必须操纵相同的状态。这意味着他们必须使用虚拟继承来继承持有状态的基类。这使设计复杂化并使其更加僵化,因为前提是用户类继承库类,反之亦然。
对于上述三个项目中的每一个,我都非常感谢一个简单的例子。每个示例都将显示多重继承的一个限制(例如,糟糕的机制)以及模板如何不具备这种限制(Andrei 写道“多重继承和模板促进互补权衡”)。