2011-06-29 18 views
11
class D: A 
{ 
    B obj; 
    C obj2; 
} 

Jaka jest tutaj kolejność konstrukcji gwarantowana?Kolejność komponentów klasy inicjalizacji

wiem, że D zostanie zbudowana po A, B i C, ale to, co naprawdę chcę wiedzieć, czy A jest gwarantowana być zbudowany przed B lub C, albo nawet czy B jest gwarantowana być zbudowane przed C

wiem, że można mieć wyraźny listy initialiser:

D(): A(), B(), C() 
{} 

ale czy to lista initialiser określić kolejność inicjalizacji?

Co więcej, czy którykolwiek z komponentów ma domyślny konstruktor, czy nie?

+1

Przestań krzyczeć na mnie! –

Odpowiedz

10

Ze standardu C++ 03 ISO/IEC 14882: 2003 (E) §12.6.2/5 [class.base.startowych]

inicjalizacji postępuje się w następujący sposób:
- pierwszy i tylko przez konstruktora klasy najbardziej pochodnej, jak to opisano poniżej, klasy wirtualne bazowy jest inicjowany w porządku pojawiania się na głębokość -pierwsze przejście od lewej do prawej skierowanego acyklicznego wykresu klas bazowych, gdzie "od lewej do prawej" jest kolejnością pojawiania się nazw klas podstawowych w bazowej specyfikacji klasy bazowej listy specyfikatorów.
- Następnie bezpośrednie klasy bazowe należy zainicjować w kolejności deklaracji, tak jak pojawiają się one na bazowej liście specyfikatorów (bez względu na kolejność inicjatorów pamięci ).
- Następnie nonstatic członkowie danych zostanie zainicjowany w kolejności, w jakiej zostały zadeklarowane w definicji klasy (ponownie, niezależnie od kolejności MEM-inicjalizatorów).
- Na koniec wykonywana jest treść konstruktora.
[Uwaga: kolejność zgłoszenie jest upoważniony do zapewnienia tej podstawy oraz elementu podobiekty są niszczone w odwrotnej kolejności inicjalizacji. ]

Więc w tym przypadku, masz gwarancję, że kolejność inicjalizacji będzie pierwsza klasa bazowa A, wówczas podobiekt B (ponieważ wydaje się na pierwszym miejscu listy członków klasy w definicji klasy), a następnie podobiekt C. Kolejność listy inicjalizatorów jest nieistotna, podobnie jak to, czy któryś z członków ma domyślny konstruktor, czy też nie - jeśli element członkowski nie ma domyślnego konstruktora i nie jest jawnie zainicjowany na liście inicjalizatora, to ma nieokreślona wartość.

9

ale czy ta lista inicjalizacyjna określa kolejność inicjowania?

Nie. Lista inicjalizacyjna nie podaje określenia kolejności inicjalizacji danych prętów i bazowych podobiektów. Członkowie są inicjowane w kolejności ich zgłoszenia, oraz podobiekty bazowe wykonane są w kolejności ich wymienienia - od lewej do prawej:

struct A : B, C {} //B is constructed before C 

Również podobiekty bazowe są zbudowane przed inicjalizacji danych członkowskich.

struct A : B, C 
{ 
     D d; 
     E e; 
}; 

Kolejność inicjalizacji w powyższej struktury:

B  => C  => d => e 
subobject subobject  member member 

I są niszczone w odwrotnej kolejności.

+0

dla jasności, to kolejność deklaracji, która kontroluje kolejność inicjowania –

+0

ok fajnie, co z klasami bazowymi a obiektami członków, czy można zagwarantować inicjalizację? Zgaduję, że techniczne klasy bazowe są zadeklarowane przed członkami, więc czy to oznacza tak? :) – matt

+0

@matt: zobacz odpowiedź teraz. – Nawaz

1

Może to przykładem złamaną kodu pomogą zilustrować:

Gdybym zdefiniować klasę tak:

class Connection { 

    boost::asio::tcp::ip::socket _socket; 
    boost::asio::io_service _io_service; 

    Connection() : _io_service(), _socket(_io_service) 
    { 
    } 
}; 

to zawiedzie we wszystkich nowoczesnych kompilatorów. Ponieważ _socket jest zdefiniowany jako pierwszy element klasy, lista inicjalizacyjna spróbuje najpierw ją zainicjować, pomimo tego, że lista inicjalizacyjna prosi kompilator o zainicjowanie najpierw _io_service. Ale ponieważ _io_service nie został jeszcze zainicjowany (konstruktor gniazda zależy od zainicjowanego _io_service), inicjalizacja _socket spowoduje błąd segfault.

Być może ktoś może zacytować odpowiednią sekcję normy, która dyktuje to zachowanie.

W drugiej połowie pytania klasy podstawowe będą zawsze inicjowane przed klasami członków.

+0

Co masz na myśli "na współczesnym kompilatorze"? Pracuję z C++, ponieważ przynajmniej TC3.0 i nie pamiętam kompilatora, który błędnie pomylił kolejność inicjacji. – sbi

Powiązane problemy