2009-06-20 8 views
120

Powiel możliwe:
Forward declaration of nested types/classes in C++Jak przesłać dalej, zadeklaruj wewnętrzną klasę?

Mam klasy jak tak ...

class Container { 
public: 
    class Iterator { 
     ... 
    }; 

    ... 
}; 

indziej, chcę przejść do pojemnika :: Iterator przez odniesienie, ale nie chcę dołączać pliku nagłówkowego. Jeśli spróbuję przesłać dalej, deklaruję klasę, otrzymuję błędy kompilacji.

class Container::Iterator; 

class Foo { 
    void Read(Container::Iterator& it); 
}; 

Kompilacja powyższy kod daje ...

test.h:3: error: ‘Iterator’ in class ‘Container’ does not name a type 
test.h:5: error: variable or field ‘Foo’ declared void 
test.h:5: error: incomplete type ‘Container’ used in nested name specifier 
test.h:5: error: ‘it’ was not declared in this scope 

Jak mogę zadeklarować tę klasę do przodu, więc nie trzeba dołączyć plik nagłówka, który deklaruje klasę Iterator?

Odpowiedz

102

To jest po prostu niemożliwe. Nie można przesyłać dalej deklaracji zagnieżdżonej struktury poza kontenerem. Możesz tylko przesłać dalej, deklarując go w kontenerze.

Musisz wykonać jedną z następujących czynności

  • Bądź klasa non-zagnieżdżona
  • Zmień kolejność zgłoszenia tak, że klasa jest zagnieżdżona w pełni zdefiniowany pierwszy
  • Utwórz klasę wspólna podstawa które mogą być używane zarówno w funkcji, jak i implementowane przez klasę zagnieżdżoną.
+2

Podstawową klasą podstawową jest najczęściej używane rozwiązanie na moim końcu. – Coyote

+0

Możesz użyć znajomego do obejścia tego, jeśli chcesz. –

+1

To źle: http: //en.cppreference.com/w/cpp/language/nested_types – Nikerboker

18

Nie wierzę naprzód oświadczając wewnętrzną klasę na niepełnej prac klasowych (bo bez definicji klasy, nie ma możliwości dowiedzenia się, czy tam rzeczywiście jest wewnętrzna klasa). Więc trzeba będzie obejmować definicję kontenera, z przodu deklarowanej klasy wewnętrzna:

class Container { 
public: 
    class Iterator; 
}; 

Następnie w osobnym nagłówku realizacji Container :: Iterator:

class Container::Iterator { 
}; 

Następnie #include tylko nagłówek pojemnik (lub nie martwić przodu deklarowania i właśnie to zarówno)

+4

Dobra odpowiedź, z wyjątkiem części w nawiasie pierwszego akapitu. "Nie ma sposobu, aby dowiedzieć się, czy rzeczywiście istnieje wewnętrzna klasa" nie ma sensu w tym kontekście i jest wątpliwe, aby być dokładnym. Cały punkt deklaracji forward jest taki, że mówisz kompilatorowi, że istnieje klasa (lub w tym przypadku klasa wewnętrzna). To twoje własne oświadczenie byłoby równie prawdziwe w przypadku normalnych klas i oznaczałoby, że nie możesz przekazać niczego, co chcesz przekazać. – Aaron

1

znam żadnego sposobu aby zrobić dokładnie to, co chcesz, ale tutaj jest obejście tego problemu, jeśli jesteś gotów do użycia szablonów:

// Foo.h 
struct Foo 
{ 
    export template<class T> void Read(T it); 
}; 

// Foo.cpp 
#include "Foo.h" 
#include "Container.h" 
/* 
struct Container 
{ 
    struct Inner { }; 
}; 
*/ 
export template<> 
    void Foo::Read<Container::Inner>(Container::Inner& it) 
{ 

} 

#include "Foo.h" 
int main() 
{ 
    Foo f; 
    Container::Inner i; 
    f.Read(i); // ok 
    f.Read(3); // error 
} 

Mamy nadzieję, że ten idiom może się przydać do Ciebie (i miejmy nadzieję, że kompilator jest oparte EDG i realizuje eksport;)).