5

Nel seguente codice, ho tentato di creare un oggetto per visualizzare l'ordine del costruttore nell'eredità multistrato, ma trovo la struttura di obj e le chiamate del costruttore in questo caso un po 'strane.Come viene costruita la base diretta nell'eredità virtuale?

#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; 
} 

Con l'uscita mostra il costruttore chiama:

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

Ma la struttura di obj alla fine del programma è in realtà:

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

So che la Base1 di obj è virtuale ereditata, ma durante la costruzione di obj, sono anche necessari la costruzione di Level2 e Level1, che porta a Base1 in ciascuna delle loro strutture. Ma l'intero processo di costruzione chiama una volta il costruttore Base1. Non posso spiegarlo. Significa che lo Base1 in Level2 e Level1 all'interno di obj condivide gli stessi dati con Base1 che appartiene direttamente a obj?

+3

L'intero punto dell'ereditarietà virtuale è che si dispone solo di * un * subobject di base virtuale. –

+0

Sapete che a differenza di C, in C++ la lista dei parametri vuota è semplicemente '()', giusto? – curiousguy

risposta

4

Ma l'intero processo di costruzione chiama una volta il costruttore Base1. Non posso spiegarlo.

La spiegazione è che Base1 è una base virtuale di tutte le classi nella gerarchia. Questo è esattamente ciò che le basi virtuali sono e per cosa sono utilizzate: condividere istanze di classi base comuni.

Citazioni da cppreference

Per ogni classe base distinta specificata virtuale, l'oggetto più derivato contiene un'unica classe base subobject di questo tipo, anche se la classe appare molte volte nella gerarchia di ereditarietà (come finché è ereditato virtuale ogni volta).

Tutti gli oggetti secondari base virtuali vengono inizializzati prima di ogni sotto-oggetto di base non virtuale, in modo che solo la classe più derivata chiama i costruttori delle basi virtuali nella sua lista dei membri di inizializzazione:

Prendendo eredità virtuale in considerazione, la vostra schema struttura potrebbe essere considerata come questo:

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

questo significa la Base1 in Level2 e Livello1 all'interno condivide obj gli stessi dati con Base1 che appartengono direttamente a obj?

Sì. Esiste esattamente un'istanza Base1 nell'intera struttura di obj.

1

Ciò significa che Base1 in Level2 e Level1 dentro obj condivide gli stessi dati con Base1 che appartiene direttamente a obj?

Sì, c'è solo un sotto-oggetto di Base1, e condivisa da base di sotto-oggetto di Level2 e Level1 in classe Leaf.

Ecco una spiegazione con l'esempio dallo standard, $ 10.1/6 classi base multipli [class.mi] (miniera sottolineato)

Per un altro esempio,

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

per un oggetto c di classe C, un singolo subobject di tipo V è condiviso da ogni sottofondo di base di c che ha una classe base virtuale di tipo V. Data la classe C definita sopra, un oggetto della classe ha un solo oggetto della classe V, come mostrato di seguito.

Problemi correlati