Grrr .. 虚拟继承必须用于抽象子类型化。如果要遵循 OO 的设计原则,就没有选择的余地。不这样做会阻止其他程序员派生其他子类型。
首先是一个抽象示例:您有一些基本抽象 A。您想创建一个子类型 B。请注意子类型必然意味着另一个抽象。如果它不是抽象的,那么它是一个实现而不是一个类型。
现在另一个程序员来了,想要制作一个 A.Cool 的子类型 C。
最后,又一个程序员出现了,想要一个既是 B 又是 C 的东西。当然也是 A。在这些场景中,虚拟继承是强制性的。
这是一个真实世界的示例:来自编译器,对数据类型进行建模:
struct function { ..
struct int_to_float_type : virtual function { ..
struct cloneable : virtual function { ..
struct cloneable_int_to_float_type :
virtual function,
virtual int_to_float_type
virtual cloneable
{ ..
struct function_f : cloneable_int_to_float_type {
在这里,function
表示函数,int_to_float_type
表示由从 int 到 float 的函数组成的子类型。Cloneable
是函数可以被克隆的特殊属性。function_f
是一个具体的(非抽象的)函数。
请注意,如果我最初没有创建function
虚拟基础,则int_to_float_type
无法混入cloneable
(反之亦然)。
一般来说,如果你遵循“严格”的 OOP 风格,你总是定义一个抽象网格,然后为它们派生实现。您严格区分仅适用于抽象和实现的子类型。
在 Java 中,这是强制执行的(接口不是类)。在 C++ 中,它不是强制执行的,您也不必遵循模式,但您应该意识到这一点,并且您正在与之合作的团队或您正在从事的项目越大,理由就越充分你需要离开它。
Mixin 类型需要在 C++ 中进行大量的内务处理。在 Ocaml 中,类和类类型是独立的,并通过结构(是否拥有方法)匹配,因此继承总是很方便。这实际上比名义打字更容易使用。Mixins 提供了一种方法来模拟仅具有名义类型的语言中的结构类型。