5

Im folgenden Code habe ich versucht, ein Leaf Objekt obj zu erstellen, um die Konstruktorreihenfolge in der mehrschichtigen Vererbung zu sehen, aber ich finde die Struktur von obj und Konstruktoraufrufen in diesem Fall ein wenig seltsam.Wie wird die direkte Basis in virtueller Vererbung aufgebaut?

#include<iostream> 
using namespace std; 
class Base1 { 
public: 
    Base1(void) { 
     cout << "class Base1" << endl; 
    } 
}; 
class Base2 { 
public: 
    Base2(void) { 
     cout << "class Base2" << endl; } 
}; 
class Level1 : public Base2, virtual public Base1 
{ 
public: 
    Level1(void) 
    { 
     cout << "class Level1" << endl; 
    } 
}; 

class Level2 : public Base2, virtual public Base1 
{ 
public: 
    Level2(void) 
    { 
     cout << "class Level2" << endl; 
    } 
}; 

class Leaf :virtual public Level2, virtual public Level1 
{ 
public: 
    Leaf(void) 
    { 
     cout << "class Leaf" << endl; 
    } 
}; 


int main(void) 
{ 
    Leaf obj; 
    return 0; 
} 

Mit dem Ausgang der Konstruktor zeigt ruft:

class Base1 
class Base2 
clase Level2 
class Base2 
class Level1 
class Leaf 

Aber die Struktur von obj am Ende des Programms ist es tatsächlich:

obj 
--Level2 
----Base2 
----Base1 
--Level1 
----Base2 
----Base1 
--Base1 

Ich weiß, die Base1 von obj ist virtual vererbt, aber während der Konstruktion von obj, Level2 und Level1 müssen auch gebaut werden, was zu Base1 in jeder ihrer Struktur führt. Aber der gesamte Konstruktionsprozess ruft nur einmal Base1 Konstruktor auf. Ich kann das nicht erklären. Bedeutet das, dass die Base1 in Level2 und Level1 innerhalb obj teilt die gleichen Daten mit Base1, die direkt zu obj gehört?

+3

Der springende Punkt der virtuellen Vererbung ist, dass Sie nur * ein * virtuelles Basisunterobjekt haben. –

+0

Sie wissen, dass im Gegensatz zu C, in C++ die leere Parameterliste einfach '()', oder? – curiousguy

Antwort

4

Aber der gesamte Konstruktionsprozess ruft Base1-Konstruktor nur einmal auf. Ich kann das nicht erklären.

Die Erklärung ist, dass Base1 eine virtuelle Basis aller Klassen in der Hierarchie ist. Dies ist genau das, was virtuelle Basen sind und wofür sie verwendet werden: Gemeinsame Basisklasseninstanzen freigeben.

Zitate von cppreference

für jede einzelne Basisklasse, die virtuell angegeben ist, enthält das abgeleitete Objekt nur eine Basisklasse Subobjekt dieser Art, auch wenn die Klasse viele Male in der Vererbungshierarchie erscheint (wie solange es jedes Mal virtuell vererbt wird).

All virtuellen Basis Subobjekte werden, bevor eine nicht-virtuelle Basis subobject initialisiert, so dass nur die abgeleitete Klasse ruft die Konstrukteure der virtuellen Basen in ihrem Mitglied Initialisiererliste:

virtuelle Vererbung Unter Berücksichtigung Ihres Strukturdiagramm könnte wie folgt betrachtet werden:

obj 
--Level2 
----Base2 
----+-------Base1 
--Level1 // 
----Base2// 
----+----//
--+-------/ 

bedeutet dies die Base1 in Level2 und Level1 innerhalb obj teilt die gleichen Daten mit Base1 der obj gehört zu direkt?

Ja. Es gibt genau eine Base1 Instanz innerhalb der gesamten Struktur von obj.

1

Bedeutet dies, dass die Base1 in Level2 und Level1 innerhalb obj die gleichen Daten mit Base1 teilt, die direkt zu obj gehört?

Ja, es gibt nur eine subobject von Base1 und geteilt durch Basis subobject von Level2 und Level1 in Klasse Leaf.

Hier ist eine Erklärung mit Beispiel aus dem Standard, $ 10.1/6 mehr Basisklassen [class.mi] (betonte Mine)

Für ein anderes Beispiel

class V { /* ... */ }; 
class A : virtual public V { /* ... */ }; 
class B : virtual public V { /* ... */ }; 
class C : public A, public B { /* ... */ }; 

für ein Objekt c von Klassentyp C, ein einzelnes Unterobjekt vom Typ V ist , das von jedem Basisunterobjekt c geteilt wird, das eine virtuelle Basisklasse vonhatTyp V. Bei der oben definierten Klasse C hat ein Objekt der Klasse C ein Unterobjekt der Klasse V, wie unten gezeigt.

Verwandte Themen