2011-12-24 9 views
37

C11 obsługuje struktury anonimowych, jak w przykładzie:Dlaczego C++ 11 nie obsługuje anonimowych struktur, a C11 to robi?

struct Foo 
{ 
    struct 
    { 
     size_t x, y; 
    }; 
}; 
struct Foo f; 
f.x = 17; 
f.y = 42; 

Zasadniczo, elementy takiego struct są traktowane tak, jakby były członkami otaczania struct lub union (rekurencyjnie, jeśli struktura otaczająca był się anonimowy).

Co było uzasadnieniem dla C++ 11, nie uwzględniając anonimowych struktur? Są one niezbyt użyteczne (głównie w związkach, aby wyeliminować wpisanie identyfikatora dla struct), z pewnością. Ale wydają się one wystarczająco oczywistym dodatkiem do specyfikacji (i już zaimplementowanym przez wiele kompilatorów), które z pewnością musiały zostać omówione, przynajmniej w celu zachowania kompatybilności ze standardem C11. Dlaczego więc nie zostały dodane?

+12

Nie zgadzam się z głosowaniem, że to pytanie nie jest konstruktywne. Miękkie pytania też są w porządku. – GManNickG

+6

__Praktycznie _ większość kompilatorów C++ 11 obsługuje również anonimowe struktury. Używałem ich zarówno w MSVC++ (od zawsze), jak iz kompilatorem C++ 11 firmy Apple. – bobobobo

+0

MinGW obsługuje również anonimowe struktury/związki. –

Odpowiedz

42

Dołożono niewielkich starań, aby zachować kompatybilność między C++ i C w miarę ewolucji dwóch języków. Zauważ, że tablice stosów o zmiennej długości były w C od 1999 roku, ale nie były zawarte w C++ 11. Chociaż zazwyczaj nie wprowadzają one elementów sprzecznych ze sobą, komitet C++ nie jest dokładnie pochylony do tyłu, aby upewnić się, że C++ 11 jest kompatybilny z wersjami C poza C89.

Co więcej, ta funkcja byłaby dość skomplikowana w C++, ponieważ struct to nic innego jak class. Anonimowa struktura/klasa powinna mieć wszystkie funkcje regularnej struktury/klasy, tak? W przeciwnym razie, jaki jest sens posiadania?

Co by to znaczyło stworzyć bezimienną struct? Jak zdefiniowałbyś konstruktora? Coś tak prostego jak:

struct Foo 
{ 
    struct 
    { 
     size_t &x; 
    }; 
}; 

po prostu nie jest możliwe, ponieważ wewnętrzna struct ma konstruktora. I nie ma sposobu, aby to określić. A struct nie może zbudować w sobie członków innego struct.

Na coś takiego:

struct Foo 
{ 
    size_t outer; 
    struct 
    { 
     void SomeFunc(); 
     size_t x; 
    }; 
}; 

Co this wskaźnik dokłada SomeFunc dostać? Jaki byłby typ this, bezimienny i nienazwany typ? Jak byś zdefiniował SomeFunc poza strukturą? Nazwa SomeFunc nie może być Foo::SomeFunc, ponieważ SomeFunc żyje w wewnętrznym zasięgu.

Jest to zbyt skomplikowane, aby C++ mogło sobie z nim poradzić. I na pewno nie na tyle, żeby zawracać sobie głowę dodawaniem tej złożoności.

+14

To ma sens, chociaż mogę sobie wyobrazić ograniczenia, które uczyniłyby go całkowicie sensownym: POD, brak metod (odziedziczonych lub innych), i w pełni publiczny, jak sądzę, rozwiązuje problemy, które podnosisz. Wydaje mi się również, że anonimowe związki zawodowe wprowadzają już wiele z tych problemów, więc problemy nie wydają mi się "zbyt skomplikowane", chyba że w sensie zbyt małego dążenia do ich rozwiązania. –

+11

"Co by to znaczyło stworzyć bezimienną strukturę? Jak zdefiniowałbyś konstruktora?". To samo można wymagać bezimiennego związku. Związki mogą również mieć konstruktorów. –

+0

Dodatkowo, większość tego, co dostajesz w C11 z anonimowych struktur, możesz również uzyskać z dziedziczenia. Anonimowe związki byłyby bardziej użyteczne, ale jak zauważa Nicol, cała ta funkcja jest kiepska dla C++. –

3

Aby zagrać w adwokata diabła - deklaracje klasy i struktury są często używane do zawijania oświadczeń typu specyficznych dla klasy.

typedef struct { 

} name; 

dlatego powinny być dopuszczalne.

Dlatego

struct { 

} 

powinny być tak dobrze.

Jednakże, jeśli uznamy to za po prostu deklarację w wewnętrznej przestrzeni nazw klasy, nie będzie możliwości uzyskania dostępu do wnętrza struktury.

Ponieważ struct! = Namespace w C, C może tworzyć reguły takie jak dostęp do anonimowej struktury przez otaczającą strukturę.

Dla C++, aby to umożliwić, musiałby w tym przypadku wystąpić sytuacja, która skomplikowałaby rozpoznawanie nazw.

Oczywiście grając diabelskiego adwokata diabła - C faktycznie to zrobił. Dodał dodatkowy poziom do rozpoznawania nazw - jeśli nie możesz znaleźć nazwy w teście, sprawdź anonimowych członków struktury. Co jest trochę magiczne, w taki sposób, że widzę denerwujące członków komitetu C++.

To także rodzi pytania - jeśli anonimowa struktura jest dostępna za pośrednictwem jej klasy nadrzędnej, to co z anonimowymi strukturami w przestrzeni nazw.

Oczywiście, jeśli naprawdę chcesz wiedzieć, po prostu zapytaj Stroustrupa - odpowiada na e-maile.

+0

To nie może być właściwy powód - anonimowe związki * są * obsługiwane (nawet w C++ 98!), Ale anonimowe struktury nie są? Jeśli to był powód, anonimowe związki nie powinny być wspierane, ponieważ dzielą one tę samą przestrzeń nazw co struktury. –

+0

Uważam, że "trochę magiczne" trochę zabawne. Dla mnie wygląda bardziej jak "To nie jest C. Decydujemy, neener-neener". – 6502

+0

C++ obsługuje już anonimowe związki i anonimowe przestrzenie nazw, w których zawartość się rozlewa, tak jakby zostały zadeklarowane w liniach zewnętrznych. Anonimowe struktury uzupełniają to trio (szczególnie przydatne w programowaniu grafiki). W innym aspekcie C++ 11 nawet wykracza poza C i obsługuje wbudowane przestrzenie nazw (nawet jeśli są nazwane, a nie tylko anonimowe). http://stackoverflow.com/questions/11016220/what-are-inline-namespaces-for –

-2

To, że to działa w C++ 11

struct A 
{ 
    int someVariable; 
}; 

struct B : public A 
{ 
    int someOtherVariable; 
}; 

Użyj go jako:

B structB; 
structB.someVariable = 5; 
structB.someOtherVariable = 6; 

To pomogło mi rozwiązać podobny problem.

Powiązane problemy