2013-03-16 11 views
19

Zastanawiam się, czy istnieje powód, dla którego nie możemy zainicjować członków na ich deklaracji.Dlaczego nie możemy zainicjować członków klasy na ich deklaracji?

class Foo 
{ 
    int Bar = 42; // this is invalid 
}; 

Jako odpowiednik korzystania z list inicjalizacyjnych konstruktora.

class Foo 
{ 
    int Bar; 
public: 
    Foo() : Bar(42) {} 
} 

Osobiście rozumiem, że powyższy przykład jest znacznie bardziej wyrazisty i celowy. Ponadto jest to krótsza składnia. I nie widzę możliwości pomylenia z innymi elementami językowymi.

Czy są jakieś oficjalne wyjaśnienia na ten temat?

+20

Możesz w C++ 11. – chris

+0

Mój kompilator powiedział mi: * "Błąd: inicjator elementu danych jest niedozwolony" *. – danijar

+2

Twój kompilator nie obsługuje jeszcze (wszystkich) C++ 11. –

Odpowiedz

18

Inicjowanie niestatycznych elementów nie może być wykonane przed C++ 11. Jeśli kompilujesz z kompilatorem C++ 11, powinieneś z radością przyjąć kod, który podałeś.

Wyobrażam sobie, że powodem, dla którego nie zezwolono na to w pierwszej kolejności, jest to, że deklaracja członka danych nie jest definicją. Nie ma obiektu, który zostanie wprowadzony. Jeśli masz element danych, taki jak int x;, nie tworzy się obiekt int, dopóki nie zostanie utworzony obiekt typu klasy. Dlatego inicjator tego elementu byłby mylący. Dopiero w trakcie budowy można przypisać wartość członkowi, do czego służą właśnie listy inicjalizacji członków.

Wystąpiły również problemy techniczne, które należało wyeliminować przed dodaniem statycznego elementu inicjującego. Rozważmy następujące przykłady:

struct S { 
    int i(x); 
    // ... 
    static int x; 
}; 

struct T { 
    int i(x); 
    // ... 
    typedef int x; 
}; 

Kiedy te struktury są przetwarzane, w momencie analizowania elementu i, jest niejednoznaczna, czy jest to deklaracja członek danych (jak w S) lub deklaracja funkcji członka (jak w T).

Z dodaną funkcjonalnością nie stanowi to problemu, ponieważ nie można zainicjować elementu składającego się z tej składni parantheses. Musisz użyć nawiasów lub równy-inicjator takich jak:

int i = x; 
int i{x}; 

te mogą być jedynie członkami danych i tak nie mamy problemu więcej.

Zapoznaj się z propozycją N2628, aby dokładniej przyjrzeć się problemom, które należało wziąć pod uwagę przy proponowaniu niestatycznych inicjalizatorów elementów.

+0

W czasie analizowania 'i'' x' jest nieznany, więc czy nie powinno to po prostu spowodować błędu kompilacji? Tradycyjnie deklaracje terminowe zostały wykorzystane do rozwiązania takich problemów. – doc

4

Głównym powodem jest to, że inicjalizacja dotyczy obiektu, lub instancji, a w deklaracji w klasie nie ma obiektu lub instancji ; nie masz tego, dopóki nie rozpoczniesz konstruowania.

Dokonano ewolucji pod tym względem. Już na samym końcu standaryzacji C++ 98, komisja dodała możliwość dodania dla statycznych elementów stałych typu integralnego --- głównie dlatego, że mogą one być używane w kontekstach, w których kompilator musi być w stanie aby zobaczyć inicjalizację. W języku C++ 11 język został rozszerzony, aby umożliwić określenie inicjatora w deklaracji , ale jest to tylko skrót, ale inicjalizacja nadal odbywa się u góry konstruktora.

+2

Inicjalizacja elementów danych będzie również nadal następować w kolejności deklaracji. –

+0

@CaptainObvlious Prawo, ale domyślam się, że James miał na myśli tylko to, że inicjalizacja zawsze występuje podczas wykonywania listy inicjującej ctor, w kolejności, w której członkowie zostali zadeklarowani tak jak powiedziałeś - zamiast np. wpływ na pozycję deklaracji członka względem deklera/definicji ctor. –

Powiązane problemy