是否存在使用非虚拟多重继承的真实示例?我想要一个主要是出于说教的原因。围绕名为A
、B
、C
和D
的类展开(其中B
和C
继承自A
,D
继承自B
和C
(,对于解释"D
对象是否应该有一个或两个A
子对象?"这个问题来说是非常好的,但对于我们为什么同时拥有这两个选项并不重要。许多例子关心我们为什么想要虚拟继承,但为什么我们不想要虚拟继承?
我知道什么是虚拟基类,以及如何在代码中表达这些东西。我知道钻石继承,并且有很多使用虚拟基类的多重继承的例子。
我能找到的最好的就是车辆。基类为Vehicle
,由Car
和Boat
继承。其中,Vehicle
具有occupants()
和max_speed()
。因此,继承自Car
和Boat
的Amphibian
在陆地和水上继承了不同的max_speed()
——这是有意义的——但也继承了不同occupants()
——这是没有意义的。因此Vehicle
子对象并不是真正独立的;这可能是另一个有趣的问题,但这不是问题。
有没有一个例子,作为一个真实世界的模型,这两个子对象是真正独立的?
您的思维就像OOP程序员一样,试图设计事物的抽象模型。与C++中的许多东西一样,C++多重继承是一种具有特殊效果的工具。它是否映射到某个OOP模型与工具本身的实用性无关。换句话说,你不需要一个"真实世界的模型"来证明非虚拟继承的合理性;您只需要一个真实的用例。
因为派生类继承基类的成员,所以在C++中,继承通常被用作一种将一组公共功能收集在一起的方法,有时与派生类的交互最少,并将此功能直接注入派生类。
Curioly Recurring Template Pattern和其他类似mixin的构造就是这样做的机制。这个想法是,你有一个基类,它是一个模板,它的模板参数是使用它的派生的类。这允许基类在没有virtual
函数的情况下访问派生类本身。
在C++中,我能想到的最简单的例子是enable_shared_from_this
,它允许其生存期当前由shared_ptr
管理的对象仅从该对象的指针/引用中实际检索到该对象的shared_ptr
。它使用CRTP来添加使shared_from_this
成为可能的派生类所需的各种成员和接口。由于继承是公共的,它还允许shared_ptr
的各种函数"启用shared_from_this"来检测特定类型中是否包含shared_from_this
内容,并对其进行正确初始化。
enable_shared_from_this
不需要虚拟继承,而且很可能与之配合不太好
现在想象一下,我有一些其他的CRTP类,它将一些其他功能注入到一个对象中。此功能与shared_ptr
无关,但它使用了CRTP和继承。
好吧,如果我现在写一些类型,想要从enable_shared_from_this
和继承其他功能,那么,这很好。不需要虚拟继承,事实上这样做只会让组合变得更加困难。
虚拟继承不是免费的。它从根本上改变了一个类型与其基类之间的关系。如果从这样的类型继承,则构造函数必须直接初始化任何虚拟基类。这种类型的布局非常奇怪,而且极不可能标准化。还有其他各种各样的东西。C++尽量不让程序员为他们不使用的功能付费,所以如果你不需要虚拟继承的特殊属性,你就不应该使用它。
这与C++具有非虚拟方法的原因相同——因为如果使用非虚拟继承,实现会更简单、更高效,因此如果您想要虚拟继承,则需要显式请求虚拟继承。由于如果您的类从不使用多重继承,则不需要虚拟继承,因此这是默认情况。