Niektóre kompilatory C ++ zezwalają na anonimowe związki i struktury jako rozszerzenie standardowego C ++. Jest to trochę cukru syntaktycznego, który czasami jest bardzo pomocny.
Jakie jest uzasadnienie, które uniemożliwia to, aby stało się to częścią normy? Czy istnieje techniczna blokada drogowa? Filozoficzny? Czy po prostu nie ma wystarczającej potrzeby uzasadnienia tego?
Oto próbka tego, o czym mówię:
struct vector3 {
union {
struct {
float x;
float y;
float z;
};
float v[3];
};
};
Mój kompilator to zaakceptuje, ale ostrzega, że „bezimienna struktura / związek” jest niestandardowym rozszerzeniem C ++ .
struct { int i; } a; a.i = 0;
(typ nie ma nazwy). Drugi to ten, którego C ++ nie obsługuje:struct { int i; }; i = 0;
(typ nie ma nazwy i ucieka do otaczającego zakresu). C ++, jednak nie obsługiwać zarówno anonimowe i anonimowe związków .Odpowiedzi:
Jak inni zauważyli, anonimowe związki są dozwolone w standardowym C ++, ale anonimowe struktury nie są.
Powodem tego jest to, że C obsługuje anonimowe związki, ale nie anonimowe struktury *, więc C ++ obsługuje te pierwsze ze względu na kompatybilność, ale nie obsługuje tych drugich, ponieważ nie jest to potrzebne do zapewnienia zgodności.
Ponadto anonimowe struktury w C ++ nie są zbyt przydatne. Zastosowanie wykazać, aby mieć struct zawierający trzy pływaki, które mogą być określone albo
.v[i]
, albo.x
,.y
i.z
wierzę, wyniki w niezdefiniowanej zachowań w C ++. C ++ nie pozwala na pisanie do jednego członka związku, powiedzmy.v[1]
, a następnie czytanie od innego członka, powiedzmy.y
. Chociaż kod, który to robi, nie jest rzadkością, w rzeczywistości nie jest dobrze zdefiniowany.Możliwości C ++ dla typów zdefiniowanych przez użytkownika zapewniają alternatywne rozwiązania. Na przykład:
struct vector3 { float v[3]; float &operator[] (int i) { return v[i]; } float &x() { return v[0]; } float &y() { return v[1]; } float &z() { return v[2]; } };
* C11 najwyraźniej dodaje anonimowe struktury, więc przyszła wersja C ++ może je dodać.
źródło
Powiem, że możesz wyczyścić swoją
vector3
deklarację, używając po prostu plikuunion
union vector3 { struct { float x, y, z; } ; float v[3] ; } ;
Jasne, anonimowe struktury były rozszerzeniem MSVC . Ale ISO C11 pozwala na to teraz, a gcc na to pozwala , podobnie jak kompilator llvm firmy Apple.
Dlaczego w C11, a nie w C ++ 11? Nie jestem pewien, ale praktycznie większość (gcc ++, MSVC ++ i kompilator C ++ firmy Apple) obsługuje je.
źródło
Nie wiem co masz na myśli. Sekcja 9.5 specyfikacji C ++, klauzula 2:
Możesz też robić takie rzeczy:
void foo() { typedef struct { // unnamed, is that what you mean by anonymous? int a; char b; } MyStructType; // this is more of a "C" style, but valid C++ nonetheless struct { // an anonymous struct, not even typedef'd double x; double y; } point = { 1.0, 3.4 }; }
Nie zawsze bardzo przydatne ... chociaż czasami przydatne w nieprzyjemnych definicjach makr.
źródło
Związki mogą być anonimowe; patrz Norma, 9.5 paragraf 2.
Jaki cel Twoim zdaniem spełnia anonimowa struktura lub klasa? Zanim zacznę spekulować, dlaczego czegoś nie ma w standardzie, chciałbym mieć pojęcie, dlaczego tak powinno być, i nie widzę zastosowania dla struktury anonimowej.
źródło
Opierając się na edycji, komentarzach i artykule MSDN: Struktury anonimowe , zaryzykuję przypuszczenie - słabo pasuje do koncepcji hermetyzacji. Nie spodziewałbym się, że członek klasy będzie bałaganił z moją przestrzenią nazw klasy poza zwykłym dodaniem jednego członka. Ponadto zmiany w strukturze anonimowej mogą wpływać na moją klasę bez pozwolenia.
źródło
Twój kod
union { struct { float x; float y; float z; }; float v[3]; };
jest jak
union Foo { int; float v[3]; };
który z pewnością jest nieważny (w C99 i wcześniej).
Powodem jest prawdopodobnie uproszczenie parsowania (w C), ponieważ w takim przypadku wystarczy sprawdzić, czy treść struktury / unii ma tylko „deklaratory deklarujące”, takie jak
To powiedziawszy, gcc i „inne kompilatory” obsługują nienazwane pola jako rozszerzenie.
Edycja: struktury anonimowe są teraz oficjalnie obsługiwane w C11 (§6.7.2.1 / 13).
źródło
union { ... }
to było inne niżstruct { ... }
. To pierwsze jest ważne, ale drugie nie.union { ... };
jest nieprawidłowy, nie jest poprawny.