2016-01-28 28 views
12

Próbuję zrobić zagnieżdżone klasy, która jest również podklasa jego rodzica:zagnieżdżone podklasy w C++

struct X { struct Y : public X {}; }; 

Niestety, to nie wydaje się być dozwolone w C++, jak g ++ generuje błąd

error: invalid use of incomplete type 'struct X'

jednak mój rzeczywisty kod ma X jako matrycy Klasa:

template<typename T> struct X 
{ struct Y : public X {}; }; 

dostaję ten sam komunikat , Ale tym razem to tylko ostrzeżenie:

warning: invalid use of incomplete type 'struct X< T >'

Moje pytanie brzmi: dlaczego to dawna sprawa nielegalne, natomiast na matrycy przypadek po prostu daje ostrzeżenie? Wersja szablonowa działa dokładnie tak, jak oczekiwałbym (mogę tworzyć instancje X<T>::Y, przesyłać je do X<T> itd.), Ale czy ostrzeżenie oznacza, że ​​nie powinienem go używać? Jakie problemy mogę napotkać, jeśli zignoruję ostrzeżenie?

+6

Podejrzewam, że otrzymasz błąd również w drugim przypadku, gdy próbujesz faktycznie utworzyć instancję 'X' –

+0

Użyj deklaracji X w przód? – LiMuBei

+2

@LiMuBei, nie możesz dziedziczyć z klasy niekompletnej (która jest przekazywana). to jest problem. – StoryTeller

Odpowiedz

2

Technicznie, jeśli chodzi o kompilator jest zaniepokojony, układ podstawy (X) nie muszą być znane dopiero szablon (X) jest instanciated. Szablon (X) nie może być utworzony, zanim nie zostanie w pełni zdefiniowany. W tym momencie znany jest jego układ.

Najprostszym sposobem, aby dostać się błąd z szablonu jest próba istantiate Y wewnątrz X:

template<typename T> struct X { 
    struct Y : public X {}; 
    Y y; 
}; 

We wcześniejszych wersjach kompilator nie było ostrzeżenie w przypadku, że można pokazać, ale został dodany w pewnym momencie. Oto dyskusja z GCC bugtracker o tym, czy ostrzeżenie jest fałszywe. Nie było pewności, czy jest to dozwolone przez standard, ale ich wniosek był taki, że nie jest dozwolone.

Tak więc żaden przypadek nie jest dozwolony w standardzie, ale GCC działa z tym ostatnim, ponieważ może.

Yam Marcovic Pokazuje, jak można zdefiniować X::Y w standardowy, zgodny sposób. Analogicznie identyczny przykład jest pokazany w trackerze gcc.

9

Aby odpowiedzieć na podstawowe pytanie: Otrzymasz ostrzeżenie, ponieważ szablon nie jest jeszcze utworzony, więc nie przeszkadza nikomu.

Sposób, aby rozwiązać ten problem, w obu przypadkach byłoby zdefiniowanie X::Y w punkcie, w którym X „s układ jest już znany, a więc Y” s układ może być właściwie wydedukować. Można zrobić:

struct X { struct Y; } 
struct X::Y {};