virtual class in diamond inheritance

Virtual class in diamond inheritance

根据我的理解,使用virtual抑制了基础class的构造函数,因此能够避免基础class的多个对象被实例化。

如果两个派生 class 的构造函数都被抑制,那么如何实例化基 class 的一个实例(虚拟 classes 从中派生)?

此外,如果基础 class 的构造函数被抑制,当我有一个新的 class 必须从虚拟 classes 之一继承时,基础 class =41=]的构造函数也被抑制了吗?

我在下面用例子解释了我的问题。

class student{ 
    int rollNo;
    public : student(int a): rollNo(a) { }
    int getRollNo() {
        return rollNo;
    }
};
class midsem : virtual public student{
    float midSemMarks;
    public : midsem(int a, float b) : student(a), midSemMarks(b) { }
    float getMidSemMarks() {
        return midSemMarks;
    }
};

class endsem : virtual public student{
    float endSemMarks;
    public : endsem(int a, float b):student(a),endSemMarks(b) { }
    float getEndSemMarks () {
        return endSemMarks;
    }
};
class total : public midsem, public endsem{
    float totalMarks;
    public:total(int a, float b, float c) :student(a), midsem(a,b), endsem(a,c) { }
    float getTotal() {
        return midsem::getMidSemMarks() + endsem::getEndSemMarks();
    }
  1. 在上面的例子中,当创建一个total的对象时,实例化了一个student的对象。 但是,如果使用 virtualendsemmidsem 中抑制 student 的构造函数,那么在创建 total 的对象时如何创建 student 的一个实例?

  2. 现在,当我想创建另一个派生自 endsem 的 class 时,将创建新的 class 的对象调用 [=14] 的构造函数=] class,因为使用 virtual 应该会抑制它?

From my understanding, using virtual suppresses the constructor of the base class, and therefore is able to avoid multiple objects of the base class being instantiated.

virtual适用于继承关系;它禁止为任何中间派生 class 调用虚拟基 class 构造函数,无论该基是否在 ctor-init-list 中明确命名(在这种情况下,这意味着您将调用没有该规则的该基的默认构造函数)。

If the constructor of both the derived class is suppressed, how is that one instance of the base class (from which the virtual classes are derived) instantiated?

虚拟基是从最派生的 class 初始化的,而不是中间的 class, 无论它们是否在其中明确提及class ctor-init-list 与否.

像往常一样不提及基 class 意味着调用默认构造函数。

这意味着这些成员,构造函数必须可以作为非静态成员从最派生的 class.

访问

如果基 class 可通过有效的可访问转换访问,则非静态成员只能在派生 class 中访问,因此:

1) 虚基的私有继承会使代码格式错误:

class PrivateBase {};
class Der : virtual PrivateBase {};
class Der2 : Der {};

(请记住,关键字 class 成员和基默认情况下都是私有的。)

隐式声明的特殊成员(构造函数、析构函数、赋值)遵循通常的规则,它们的定义必须有效,就好像它们是显式编写的一样;所以要使 Der2 有效,默认构造函数的 Der2(); 定义和 Der2::Der2 () {} 必须有效。

所以 Der () {} 实际上意味着 Der () : PrivateBase () {}(有效)但是 Der2 () : PrivateBase(), Der() {} 是错误的。

2) 由于虚拟继承固有的多条访问路径,并且只需要一个可访问路径,虚拟私有继承几乎从不阻止 class 派生自:

class PrivateBase {};
class Der : virtual PrivateBase {};
class Der2bis : Der, virtual PrivateBase {};

Der2bis 变体几乎与 Der2 相似,只是再次继承了虚拟基础,这使得语义差异几乎为零(某些数据结构的布局可能会发生变化),除了事实Der2bis 的虚拟 PrivateBase 基础现在可以直接访问 class 成员的 Der2bis -> PrivateBase 派生到基础转换的可访问性是给定的(转换仍然不是可从其他代码访问)。

3) 这意味着仅当派生程度最高的 class 成为基类的友元时,才能使用私有构造函数。这意味着一些 classes 可以派生自,但没有有效的构造函数定义:

class TheFriend;

class AllPrivate {
  AllPrivate ();
  AllPrivate (AllPrivate&);
  friend class TheFriend;
};

class TheFriend : virtual AllPrivate { };

请注意,TheFriend 只能默认构造其基础 class 子对象(通过命名其默认构造函数)作为其友元。

但进一步推导将失败,即使重复私有基础以使其可访问:

class MoreDerived : TheFriend, virtual AllPrivate {};

这里私有基类是可访问的,但它的成员仍然不可访问,MoreDerived 不是友元,它不能调用基类构造函数,所以它的构造函数的 none,无论是隐式的还是明确定义,可以是良构的。