2015-07-20 19 views
9

Czy kolejność niszczenia jest dobrze zdefiniowana w przypadku dziedziczenia wielokrotnego?Porządek zniszczenia w przypadku wielokrotnego dziedziczenia

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

Dla danego kodu moje wydruki kompilatora:

AB 
B 
A 

buf używam bardziej skomplikowanych konstrukcji (w tym CWinApp), otrzymuję różne rezultaty. Czy porządek jest dobrze zdefiniowany? A jeśli tak, to jaka jest zasada porządkowania?

+4

Tak, zniszczenie odbywa się w kolejności odwrotnej do deklaracji. –

+3

Który kompilator używasz, aby to wydrukować? Powinien AB, A, B. – Barry

+0

Używam Visual Studio 2013 – user1235183

Odpowiedz

14

Z [class.dtor]

ramy i elementy są zniszczone w odwrotnej kolejności zakończeniu ich konstruktor (patrz 12.6.2).

Kolejność konstruktor z [class.base.init]

W nie przekazaniu konstruktora przechodzi inicjalizacji w następującej kolejności:
- pierwszy i tylko dla konstruktora najbardziej pochodna klasa (1.8), wirtualne klasy bazowe są inicjowane [...]
- Następnie, bezpośrednie klasy bazowe są inicjalizowane w kolejności deklaracji, ponieważ pojawiają się na bazowej liście specyfikującej(niezależnie od kolejności mem-init ializery).

Dla przykładu:

struct AB : public B, public A 

Kolejność budowy jest B następnie A następnie AB. Tak więc kolejność niszczenia to AB, a następnie A, a następnie B.

6

C++ 11, norma to jasne (S10.1) dla wielu dziedziczenie

Kolejność wyprowadzenia nie jest istotny z wyjątkiem określonym przez semantyki inicjalizacji przez konstruktora (12.6.2), czyszczenia (12.4), i układu pamięci (9.2, 11.1).

Ale możesz zagwarantować, że zlecenie zniszczenia jest odwrotnością konstrukcji.

+0

Oznacza to, że każda kolejność zniszczenia jest możliwa? – user1235183

+1

Tak więc kolejność nie jest znacząca, z wyjątkiem czyszczenia. Jaka jest kolejność porządkowania? – Barry

1

Z friendly manual abbreviating nr 2 (nieco):

  1. klasy za destruktor jest tzw.
  2. Destruktory dla niestatycznych elementów w odwrotnej kolejności do deklaracji.
  3. Destruktory dla nie-wirtualnych klas bazowych są wywoływane w odwrotnej kolejności deklaracji.
  4. Destruktory wirtualnych klas bazowych są wywoływane w odwrotnej kolejności deklaracji.

więc kompilator emituje kod, który niszczy w kolejności AB, B, A.

[Edytuj 20150725: powtarzające się komentarze Barry'ego ostatecznie doprowadziło mnie zauważyć, że ja typoed „To nie jest” jak "To jest również". Oczywiście, po wpisaniu go, nie mogłem go zobaczyć, dopóki I nie zrobił. Meh. Tak więc, jeden zmienił słowo poniżej.]

To nie kolejność od isocpp.org na FAQ. Ten wpis odnosi się do tego samego pytania o zamawianie konstruktorów, gdzie tekst "Zauważ, że rozkaz B1, a następnie B2 (lub B1a, a następnie B1b) jest określony przez porządek, w którym klasy bazowe pojawiają się w deklaracji klasy, a nie w kolejności że inicjator pojawia się na liście inicjującej klasy pochodnej. " pojawia się, podkreślając, że kolejność deklaracji jest odpowiednim zleceniem.

+0

Mówisz "odwrotna kolejność deklaracji", ale wtedy mówisz "AB, B, A". Który to jest? B został zadeklarowany przed A. – Barry

+0

@ Barry: Ze źródła: struct A jest zadeklarowane w linii 1 (i natychmiast zdefiniowane), wtedy struktura B jest zadeklarowana na linii 6, wtedy struktura AB jest zadeklarowana w linii 11. Zatem, wyraźnie, A jest zadeklarowane przed B. Dodatkowo, to zamówienie faktycznie odpowiada wynikowi jego próbki kodu. –

+0

Jest to kolejność, w której są one zadeklarowane jako podstawy, które mają znaczenie, a nie kolejność, w jakiej klasy są zadeklarowane. Na podstawowej liście specyfikatorów B jest pierwsza. – Barry

Powiązane problemy