Qual è l'ordine in cui i distruttori e i costruttori sono chiamati in C ++
-
19-08-2019 - |
Domanda
Qual è l'ordine in cui i distruttori e i costruttori sono chiamati in C ++? Utilizzando gli esempi di alcune classi Base e classi derivate
Soluzione
L'ordine è:
- Costruttore di base
- Costruttore derivato
- Distruttore derivato
- Base destructor
Esempio:
class B
{
public:
B()
{
cout<<"Construct B"<<endl;
}
virtual ~B()
{
cout<<"Destruct B"<<endl;
}
};
class D : public B
{
public:
D()
{
cout<<"Construct D"<<endl;
}
virtual ~D()
{
cout<<"Destruct D"<<endl;
}
};
int main(int argc, char **argv)
{
D d;
return 0;
}
Output dell'esempio:
Costruisci B
Costruisci D
Distruggi D
Distruggi B
Più livelli di ereditarietà funzionano come una pila:
Se consideri di spingere un oggetto sulla pila come costruzione e di toglierlo come distruzione, puoi guardare a più livelli di eredità come una pila.
Funziona per qualsiasi numero di livelli.
L'esempio D2 deriva da D deriva da B.
Premi B sulla pila, premi D sulla pila, premi D2 sulla pila. Quindi l'ordine di costruzione è B, D, D2. Quindi per scoprire l'ordine di distruzione iniziare a scoppiare. D2, D, B
Esempi più complicati:
Per esempi più complicati, consultare il link fornito da @JaredPar
Altri suggerimenti
Una descrizione dettagliata di questi eventi, inclusa l'ereditarietà virtuale e multipla, è disponibile nella FAQ Lite di C ++. Sezione 25.14 e 25.15
https://isocpp.org/wiki/faq/ multiple-eredità # mi-vi-ctor-ordine
Inoltre, tieni presente che mentre gli elementi dell'array sono costruiti per primi - > infine, vengono distrutti nell'ordine inverso: last - > prima.
Devo aggiungere alle risposte precedenti perché tutti sembrano ignorarlo
Quando hai un'istanza di classe derivata in fase di creazione , è vero che il codice inside il costruttore della base verrà chiamato prima del codice inside il costruttore del derivato , ma tieni presente che il derivato è ancora tecnicamente " creato " prima della base .
E quando si chiama il derivato di classe distruttore di classe, è vero che il codice inside il distruttore derivato si chiama prima del codice all'interno il distruttore di base, ma tieni anche presente che la base è distrutta prima del derivato .
Quando dico creato / distrutto in realtà mi riferisco a allocato / deallocato .
Se guardi il layout di memoria di queste istanze, vedrai che l'istanza derivata compone l'istanza di base. Ad esempio:
Memoria derivata: da 0x00001110 a 0x00001120
Memoria di base: da 0x00001114 a 0x00001118
Pertanto, la classe derivata deve essere allocata PRIMA della base nella costruzione. E la classe derivata deve essere deallocata DOPO la base nella distruzione.
Se hai il seguente codice:
class Base
{
public:
Base()
{
std::cout << "\n Base created";
}
virtual ~Base()
{
std::cout << "\n Base destroyed";
}
}
class Derived : public Base
{
public:
Derived()
// Derived is allocated here
// then Base constructor is called to allocate base and prepare it
{
std::cout << "\n Derived created";
}
~Derived()
{
std::cout << "\n Derived destroyed";
}
// Base destructor is called here
// then Derived is deallocated
}
Quindi, se hai creato Derived d;
e l'hai fatto uscire dal campo di applicazione, otterrai l'output nella risposta di @ Brian. Ma il comportamento dell'oggetto in memoria non è proprio nello stesso ordine, è più simile a questo:
Edilizia:
-
Derivato allocato
-
Base allocata
-
Costruttore di base chiamato
-
Costruttore derivato chiamato
Distruzione:
-
Distruttore derivato chiamato
-
Distruttore di base chiamato
-
Base deallocata
-
Derivato deallocato