2015-07-20 3 views
9

L'ordine di distruzione è ben definito in caso di ereditarietà multipla?Ordine di distruzione in caso di eredità multipla

struct A 
{ 
    ~A(){std::cout << "A\n";} 
}; 

struct B 
{ 
    ~B(){std::cout << "B\n";} 
}; 

struct AB : public B, public A 
{ 
    ~AB(){std::cout<<"AB\n";} 
}; 

int main() 
{ 
    AB ab; 
} 

Per il codice data mie stampe compilatore:

AB 
B 
A 

Buf che uso costrutti più complessi (tra cui CWinApp), ottengo risultati diversi. Quindi l'ordine è ben definito? E se sì, qual è la regola di ordinazione?

+4

Sì, la distruzione è nell'ordine inverso rispetto alla dichiarazione. –

+3

Quale compilatore stai facendo che è quello che viene stampato? Dovrebbe AB, A, B. – Barry

+0

Sto usando Visual Studio 2013 – user1235183

risposta

14

Da [class.dtor]:

Basi e membri sono distrutti in ordine inverso del completamento della loro costruzione (vedi 12.6.2).

L'ordine di costruzione, da [class.base.init]:

In un costruttore non delega, procede inizializzazione nel seguente ordine:
- primo, e solo per il costruttore la classe più derivata (1.8), le classi di base virtuali sono inizializzate [...]
- Quindi, le classi di base dirette vengono inizializzate in ordine di dichiarazione come appaiono nell'elenco specificatore di base (indipendentemente dall'ordine di il mem-init ializzatori).

Per esempio:

struct AB : public B, public A 

L'ordine di costruzione è B quindi A poi AB. Quindi l'ordine di distruzione è AB quindi A quindi B.

6

Il C++ 11 standard rende chiaro (S10.1), per ereditarietà multipla

L'ordine di derivazione non è significativo tranne quanto specificato dalle semantica di inizializzazione di costruzione (12.6.2), cleanup (12.4), e layout di archiviazione (9.2, 11.1).

Ma si può garantire che l'ordine di distruzione è il rovescio della costruzione.

+0

Questo significa che ogni ordine di distruzione è possibile? – user1235183

+1

Quindi l'ordine non è significativo tranne per la pulizia. Qual è l'ordine per la pulizia? – Barry

1

Dal friendly manual (abbreviando # 2 un po '):

  1. distruttore della classe si chiama.
  2. Distruttori per membri non statici in ordine inverso alla dichiarazione.
  3. I distruttori per classi base non virtuali sono richiamati nell'ordine inverso di dichiarazione.
  4. I distruttori per le classi di base virtuali vengono richiamati nell'ordine inverso di dichiarazione.

Quindi il compilatore emette codice che distrugge nell'ordine AB, B, A.

[Edit 20.150.725: commenti ripetuti di Barry alla fine mi ha portato a notare che avevo typoed "Questo non è" come "Questo è anche". Naturalmente, dopo averlo digitato, non sono riuscito a vederlo fino a quando non ho effettuato il . Meh. Così, quello ha cambiato parola nel seguito.]

Questo è non l'ordine da isocpp.org di FAQ. Quella voce si riferisce alla stessa domanda sull'ordinazione del costruttore, dove il testo "Si noti che l'ordine B1 e poi B2 (o B1a poi B1b) è determinato dall'ordine in cui le classi di base compaiono nella dichiarazione della classe, non nell'ordine che l'inizializzatore appare nell'elenco di inizializzazione della classe derivata. " appare, evidenziando che l'ordine di dichiarazione è l'ordine pertinente.

+0

Dici "ordine inverso di dichiarazione", ma poi dici "AB, B, A". Cos'è questo? B è stato dichiarato prima di A. – Barry

+0

@Barry: Dalla sorgente: la struct A è dichiarata sulla riga 1 (e immediatamente definita), quindi la struct B è dichiarata sulla riga 6, quindi la struct AB è dichiarata sulla riga 11. Quindi, chiaramente, A è dichiarato prima di B. Inoltre, questo ordine corrisponde effettivamente all'output del suo esempio di codice. –

+0

È l'ordine in cui vengono dichiarati come basi importanti, non l'ordine in cui le classi stesse sono dichiarate. Nell'elenco degli specificatori di base, B è il primo. – Barry