2010-10-27 25 views
2

Le code suivant:erreur de compilation C++ ENUM "ne désigne pas un type"

foo.h

#include "bar.h" 
class foo{ 
public: 
    enum my_enum_type { ONE, TWO, THREE }; 
    foo(); 
    ~foo() {} 
}; 

foo.cpp

foo::foo() 
{ 
    int i = bar::MY_DEFINE; 
} 

bar.h

#include "foo.h" 
class bar{ 
public: 
    static const int MY_DEFINE = 10; 
    foo::my_enum_type var; 
    bar() {}; 
    ~bar() {}; 
}; 

Le compilateur g ++ se plaint de my_enum_type "ne nomme pas un type". Pourquoi? Tous les en-têtes ont des définitions d'inclusion multiples (non présentées ici pour plus de clarté).

Merci

+1

Cela devrait fonctionner correctement ... –

+1

Comment utilisez-vous les classes? Vous n'avez pas encore de fichier source ici. Pouvez-vous partager comme vous utilisez ces classes? –

+1

Merci les gars, vous me faites réaliser que le problème n'était pas la syntaxe, mais comment j'ai utilisé les classes. Il y avait un #include "bar.h" dans foo.h, je l'ai remplacé par une déclaration avant et tout va bien maintenant! –

Répondre

2

Vous devez supprimer la dépendance cyclique, vous devez donc considérer foo.cpp et foo.h comme des unités différentes à cette fin.

  • bar définition de classe doit voir foo :: my_enum_type donc bar.h probablement y compris foo.h est une nécessité.

  • définition de la classe foo n'utilise pas de bar, donc foo.h n'a pas besoin d'inclure bar.h

  • foo.cpp n'a pas besoin de voir la barre pour MY_DEFINE si foo.cpp devrait inclure bar. h. Cela amènerait aussi automatiquement foo.h mais vous voudrez peut-être l'inclure quand même dans foo.cpp, juste au cas où vous supprimeriez la dépendance plus tard.

Vos en-têtes ont probablement plusieurs protections.

+1

Je ne savais pas que vous deviez considérer les dépendances .h et .cpp séparément. Je pensais inclure plus d'un .h dans un .cpp était mauvaise conception. J'avais probablement tort, votre réponse a résolu mon problème. Merci :) –

4

Problèmes:

  • aucune protection d'inclusion multiples
  • inclusion cyclique
  • utilisation de type avant sa déclaration provoquée par l'inclusion cyclique

Votre foo.h en cours de traitement par le préprocesseur C ressemble à une séquence de chaînes vide infinie.

avec de multiples protection d'inclusion foo.h est prétraité à:

> cpp foo.h 
class bar{ // preprocessed from #include "bar.h" 
public: 
    static const int MY_DEFINE = 10; 
    foo::my_enum_type var; 
    bar() {}; 
    ~bar() {}; 
}; 
// end of #include "bar.h" 
class foo{ 
public: 
    enum my_enum_type { ONE, TWO, THREE }; 
    foo(); 
    ~foo() {} 
}; 

Ceci est évidemment pas un code C++ valide - foo est utilisé dans le corps de bar sans déclaration préalable. C++, contrairement à Java, nécessite que les types soient déclarés avant utilisation.

  • Utiliser une protection d'inclusion multiple. Selon votre plate-forme, ceux-ci peuvent être des macros #ifndef ou #pragma once des directives
  • Supprimer l'inclusion de bar.h de foo.h.
  • Placez les déclarations anticipées si nécessaire (dans votre cas, bar peut être déclaré dans foo.h, votre exemple ne révèle cependant pas la nécésité).
  • Déplacer autant d'implémentation que possible vers les fichiers * .cpp.

Si la situation ne peut pas être résolue avec ces recommandations, utilisez PIMPL idiom.

En bref - il suffit de retirer #include "bar.h" directive de foo.h

+0

Mes en-têtes ont une protection d'inclusion multiple. Si je supprime bar.h de foo.h, foo.cpp ne peut plus utiliser bar :: MY_DEFINE ('bar' n'a pas été déclaré). –

+0

Mauvais. foo.cpp peut toujours utiliser la barre si vous incluez bar.h dans foo.cpp lui-même. – Basilevs

+0

Oui, c'est ce que je ne savais pas;) –

2
foo() 
{ 
    int i = bar::MY_DEFINE; 
} 

devrait être

foo::foo() 
{ 
    //... 
} 

Notez également que

static const int MY_DEFINE = 10; 

est encore une déclaration, même si elle a un initialiseur. En bar.cpp vous devriez avoir la ligne suivante

const int bar::MY_DEFINE; 

vous pouvez également inclure bar.h pas de foo.h et foo.h de bar.h ... qui est physiquement impossible :)