2009-06-20 16 views
120

Eventuali duplicati:
Forward declaration of nested types/classes in C++Come inoltrare dichiaro una classe interna?

Ho una classe in questo modo ...

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

    ... 
}; 

Altrove, voglio passare un contenitore :: Iterator per riferimento, ma non voglio includere il file di intestazione. Se provo ad inoltrare la classe, ottengo errori di compilazione.

class Container::Iterator; 

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

Compilare il codice di cui sopra dà ...

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 

Come posso avanti dichiarare questa classe in modo da non dover includere il file di intestazione che dichiara la classe Iterator?

risposta

102

Questo semplicemente non è possibile. Non è possibile inoltrare la dichiarazione di una struttura nidificata all'esterno del contenitore. È possibile inoltrare solo dichiararlo all'interno del contenitore.

Avrai bisogno di effettuare una delle seguenti

  • rendere la classe non annidata
  • cambiare l'ordine di dichiarazione in modo che la classe annidata è completamente definito prima
  • Creare una classe base comune che può essere utilizzato entrambi nella funzione e implementato dalla classe annidata.
+2

La classe di base comune è la soluzione più utilizzata sul mio terminale. – Coyote

+0

Puoi usare un amico per aggirare questo, se vuoi. –

+1

Questo è sbagliato: http: //en.cppreference.com/w/cpp/lingua/nested_types – Nikerboker

18

Io non credo in avanti dichiarando di classe interna su una classe opere incomplete (perché senza la definizione della classe, non c'è modo di sapere se c'è davvero è una classe interna). Quindi si dovrà includere la definizione di contenitore, con una classe interna in avanti dichiarato:

class Container { 
public: 
    class Iterator; 
}; 

Poi, in un colpo di testa a parte, attuare Container :: Iterator:

class Container::Iterator { 
}; 

Poi # include solo la intestazione del contenitore (o non preoccuparsi avanti dichiarando e proprio includono entrambi)

+4

Buona risposta, tranne la parte nella parentesi del primo paragrafo. Il "non c'è modo di sapere se esiste effettivamente una classe interiore" non ha senso in questo contesto ed è dubbio che sia accurato. L'intero punto di una dichiarazione avanzata è che stai dicendo al compilatore che esiste una classe (o, in questo caso, una classe interiore). Quella tua affermazione specifica sarebbe altrettanto vera per le classi normali e significherebbe che non puoi inoltrare nulla. – Aaron

1

non conosco nessun modo di fare esattamente quello che vuoi, ma qui è una soluzione alternativa, se si è disposti a utilizzare i modelli:

// 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 
} 

Speriamo che questo linguaggio potrebbe essere di qualche utilità per voi (e si spera il compilatore è basato EDG ed implementa l'esportazione;)).

Problemi correlati