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

È stato utile?

Soluzione

L'ordine è:

  1. Costruttore di base
  2. Costruttore derivato
  3. Distruttore derivato
  4. 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:

  1. Derivato allocato

  2. Base allocata

  3. Costruttore di base chiamato

  4. Costruttore derivato chiamato

Distruzione:

  1. Distruttore derivato chiamato

  2. Distruttore di base chiamato

  3. Base deallocata

  4. Derivato deallocato

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top