我了解基类的虚拟继承在多个派生类之间创建了一个公共共享基类,从而解决了 DDD 问题。如果我的基类只有一个派生类,那么虚拟继承或非虚拟继承基类有区别吗?基本上我试图理解查询中提供的解释是否可以在编译时禁止从类派生?其中 Usage_lock 基类是虚拟继承的,以防止从类 Usable 派生。如果我删除这个虚拟键,行为就会改变,即我能够从 Usable 派生子类。所以我想了解单继承场景中虚拟键造成的差异。
3 回答
单个虚拟继承情况的主要区别在于,只有最派生的类调用虚拟继承基类的构造函数,而所有其他类都提供了对所构造类的引用(这发生在幕后)。
因此,在示例中,由于尝试进一步派生Usable
将需要新类调用Usable_lock
构造函数(这是私有的),因此任何其他类都不可能从Usable
. 只Usable
允许构造锁对象,因为它是锁的朋友。
虚拟继承基本上是为了解决Diamond shaped Inheritance
.
考虑以下类:
class Base {};
class Derived1: Base {};
class Derived2: Base {};
struct MostDerived: Derived1, Derived2 {};
MostDerived
Base
由于这个菱形层次结构,这里的类有 2 个实例。
为了解决这个问题,C++ 使用virtual
关键字并引入了称为虚拟继承的概念。
因此在virtual
此处添加关键字,如下所示:
class Derived1: virtual Base {};
class Derived2: virtual Base {};
确保现在只有一个Base
内部MostDerived
类实例。
并且该类通过调用其构造函数来MostDerived
实例化该类的实例。Base
使用上述背景(强调粗体文本),请考虑以下代码示例:
Usable
类实际上派生自Usable_lock
,因此派生类Usable
必须通过调用其构造函数来实例化Usable_lock
对象的基类。
但是Usable_lock
类有一个私有构造函数,所以只有类本身可以访问构造函数,从而防止其他类从它派生。
来自 C++03 标准的参考:
第 12.6.2 节初始化基和成员
第 6 段:
所有代表虚拟基类的子对象都由最派生类的构造函数初始化(1.8)。如果最派生类的构造函数没有为虚拟基类 V 指定 mem-initializer,则调用 V 的默认构造函数来初始化虚拟基类子对象。如果 V 没有可访问的默认构造函数,则初始化格式不正确。在执行任何不是最派生类的类的构造函数期间,应忽略命名虚拟基类的 mem-initializer。
虚拟基类将由最派生的类构造。通过虚拟派生,并使此类基类的构造函数私有,其他类无法构造它,因此有效地防止了派生。然而,它是一个相当人为的构造,而且它也带来了一些开销。