2009-06-20 8 views
120

Possible en double:
Forward declaration of nested types/classes in C++Comment transférer une classe interne?

J'ai une classe comme si ...

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

    ... 
}; 

Ailleurs, je veux passer un conteneur :: iterator par référence, mais je ne veux pas inclure le fichier d'en-tête. Si j'essaie de transmettre la classe, j'obtiens des erreurs de compilation.

class Container::Iterator; 

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

le code ci-dessus Compiler donne ...

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 

Comment puis-je déclarer avant cette classe, donc je n'ai pas d'inclure le fichier d'en-tête qui déclare la classe Iterator?

Répondre

102

Ceci n'est simplement pas possible. Vous ne pouvez pas transférer une structure imbriquée en dehors du conteneur. Vous pouvez uniquement le transférer dans le conteneur.

Vous devez faire une des opérations suivantes

  • Faire la classe non-imbriquée
  • Changer votre commande de déclaration afin que la classe imbriquée est entièrement défini en premier
  • Créer une classe de base commune Cela peut être à la fois utilisé dans la fonction et implémenté par la classe imbriquée.
+2

La classe de base commune est la solution la plus utilisée de mon côté. – Coyote

+0

Vous pouvez utiliser un ami pour contourner ce problème, si vous le souhaitez. –

+1

C'est faux: http: //en.cppreference.com/w/cpp/langue/nested_types – Nikerboker

18

Je ne crois pas déclarer avant la classe intérieure sur un fonctionnement de classe incomplète (car sans la définition de classe, il n'y a pas moyen de savoir s'il y a effectivement est une classe interne). Donc, vous devrez inclure la définition du conteneur, avec une classe interne déclarée avant:

class Container { 
public: 
    class Iterator; 
}; 

Puis, dans un en-tête séparée, implémentez Container :: iterator:

class Container::Iterator { 
}; 

Alors #include seulement tête de conteneur (ou vous inquiétez pas pour déclarer avant et juste comprennent à la fois)

+4

Bonne réponse, sauf la partie de la parenthèse du premier paragraphe. Le "il n'y a aucun moyen de savoir s'il existe réellement une classe interne" n'a pas de sens dans ce contexte et est douteux d'être précis. Le but entier d'une déclaration forward est que vous dites au compilateur qu'il y a une classe (ou dans ce cas, une classe interne). Cette déclaration spécifique serait tout aussi vraie pour les classes normales et signifierait que vous ne pouvez pas transmettre quelque chose. – Aaron

1

Je ne connais aucun moyen de faire exactement ce que vous voulez, mais voici une solution de contournement, si vous êtes prêt à utiliser des modèles:

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

Espérons que cet idiome pourrait être utile pour vous (et nous espérons que votre compilateur est EDG-base et met en œuvre l'exportation;)).

Questions connexes