web-dev-qa-db-fra.com

Comment puis-je déclarer une classe interne?

Duplicate possible:
Déclaration en aval de types/classes imbriquées en C++

J'ai un cours comme ça ...

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, les erreurs de compilation sont générées.

class Container::Iterator;

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

Compiler le code ci-dessus 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 transférer la déclaration de cette classe afin de ne pas avoir à inclure le fichier d'en-tête qui déclare la classe Iterator?

143
bradtgmurray

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

Vous devrez faire l'une des choses suivantes

  • Rendre la classe non imbriquée
  • Modifiez votre ordre de déclaration afin que la classe imbriquée soit entièrement définie en premier
  • Créez une classe de base commune pouvant être utilisée dans la fonction et implémentée par la classe imbriquée.
125
JaredPar

Je ne crois pas que la déclaration en avant d'une classe interne sur une classe incomplète fonctionne (car sans la définition de classe, il est impossible de savoir s'il existe réellement est une classe interne). Vous devrez donc inclure la définition de conteneur, avec une classe interne déclarée en avant:

class Container {
public:
    class Iterator;
};

Ensuite, dans un en-tête séparé, implémentez Container :: Iterator:

class Container::Iterator {
};

Puis, n'incluez que l'en-tête du conteneur (ou ne vous inquiétez pas de la déclaration en aval et n'incluez que les deux)

23
Todd Gardner

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 vous être utile (et que votre compilateur est basé sur EDG et implémente export;)).

1
Faisal Vali