2009-03-17 9 views

Répondre

49

L'ordre est:

  1. constructeur de base
  2. constructeur dérivé
  3. destructor dérivé
  4. base destructor

Exemple:

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

Sortie d'exemple:

Construct B

Construct D

Destruct D

Destruct B

Plusieurs niveaux d'héritage fonctionne comme une pile:

Si vous envisagez de pousser un élément sur la pile que la construction et l'enlever comme la destruction, alors vous pouvez regarder à plusieurs niveaux d'héritage comme une pile.

Cela fonctionne pour n'importe quel nombre de niveaux.

Exemple D2 dérive D dérive de B.

poussoir B sur la pile, pousser D sur la pile, pousser D2 sur la pile. Donc, l'ordre de construction est B, D, D2. Ensuite, pour connaître l'ordre de destruction, commencez à sauter. D2, D, B

Des exemples plus complexes:

Pour des exemples plus compliqués, s'il vous plaît voir le lien fourni par @JaredPar

+1

Peut-être que l'OP veut connaître la classe D: public A, B, C ... –

+1

L'héritage multiple ajoute de la complexité: http://www.gotw.ca/gotw/080.htm –

9

De plus, gardez à l'esprit que si les éléments du tableau sont construits d'abord -> dernier, ils sont détruits dans l'ordre inverse: dernière -> première.

+1

+1 C'est vrai pour presque tout. L'ordre de destruction est toujours le contraire de la construction. Les variables statiques n'ont pas d'ordre de construction garanti, mais la destruction se fera dans l'ordre inverse. –

+0

Est-ce que le comportement du conteneur est un modèle (attendu) et/ou un comportement intégré 'new []'/'delete []'? – franji1

2

Je dois ajouter aux réponses précédentes parce que tout le monde semble ignorer

Lorsque vous avez un dérivé instance de classe étant créé, il est vrai que le code intérieur le constructeur de la base sera appelé avant le code intérieur le constructeur de la dérivé, mais gardez à l'esprit que le dérivé est toujours techniquement « créé »avant la base .

Et quand vous avez la destructor classe dérivé appelé, il est vrai que le code intérieur le destructor dérivé est appelé avant le code intérieur la destructor de base, mais aussi garder dans l'esprit que le base est détruitavant le dérivé.

Quand je dis créé/détruit Je me réfère en fait à alloué/deallocated.

Si vous regardez la disposition de la mémoire de ces instances, vous verrez que l'instance dérivée compose l'instance de base. Par exemple:

Mémoire dérivée: 0x00001110 0x00001120 à

Mémoire de base: 0x00001114 0x00001118 à

Par conséquent, la classe dérivée doit être allouée AVANT la base dans la construction. Et la classe dérivée doit être désaffectée APRÈS la base dans la destruction.

Si vous avez le code suivant:

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 
} 

Donc, si vous avez créé Derived d; et l'avait hors de portée, alors vous obtiendrez la sortie dans @ la réponse de Brian.Mais le comportement de l'objet en mémoire est pas vraiment en ordre, il est plus comme ceci:

Construction:

  1. Dérivée alloués

  2. base AFFECTÉ

  3. constructeur de base appelé Constructeur dérivé appelé

Destruction:

  1. destructor dérivé appelé

  2. destructor de base appelée

  3. base désallouée

  4. Dérivé désattribuées

Questions connexes