Przed C ++ 11 mogliśmy wykonywać inicjalizację w klasie tylko na statycznych elementach stałych typu integralnego lub wyliczeniowego. Stroustrup omawia to w swoim C ++ FAQ , podając następujący przykład:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
I następujące rozumowanie:
Dlaczego więc istnieją te niewygodne ograniczenia? Klasa jest zwykle deklarowana w pliku nagłówkowym, a plik nagłówkowy jest zwykle dołączany do wielu jednostek tłumaczeniowych. Jednak aby uniknąć skomplikowanych reguł konsolidatora, C ++ wymaga, aby każdy obiekt miał unikalną definicję. Ta reguła zostałaby złamana, gdyby C ++ pozwolił na definiowanie w klasie jednostek, które musiałyby być przechowywane w pamięci jako obiekty.
Jednak C ++ 11 łagodzi te ograniczenia, umożliwiając inicjalizację w klasie niestatycznych elementów członkowskich (§12.6.2 / 8):
W konstruktorze nie delegującym, jeśli dany niestatyczny element członkowski danych lub klasa bazowa nie jest wyznaczony przez identyfikator-inicjalizatora-pamięci (w tym przypadek, w którym nie ma listy inicjalizatora-pamięci, ponieważ konstruktor nie ma inicjatora-inicjatora ) a więc jednostka nie jest wirtualną klasą bazową klasy abstrakcyjnej (10.4)
- jeśli jednostka jest niestatycznym składnikiem danych, który ma inicjator nawiasu klamrowego lub równego , jednostka jest inicjowana zgodnie z pkt 8.5;
- w przeciwnym razie, jeśli jednostka jest składnikiem wariantowym (9.5), inicjalizacja nie jest wykonywana;
- w przeciwnym razie jednostka jest inicjalizowana domyślnie (8.5).
Sekcja 9.4.2 zezwala również na inicjowanie w klasie niestatycznych elementów członkowskich, jeśli są one oznaczone constexpr
specyfikatorem.
Więc co się stało z przyczynami ograniczeń, które mieliśmy w C ++ 03? Czy po prostu akceptujemy „skomplikowane reguły konsolidatora”, czy też zmieniło się coś jeszcze, co ułatwia implementację?