J'ai donc une classe incluse dans une autre classe qui continue à générer une erreur de compilation du type "erreur: 'ProblemClass' n'a pas été déclaré. Les fichiers sont configurés de la manière suivante:
#ifndef PROBLEMCLASS_H
#define PROBLEMCLASS_H
#include <iostream>
#include <cmath>
class ProblemClass
{
public:
virtual void Init() = 0;
};
#endif
et la classe où l'erreur se produit ressemble à ceci:
#ifndef ACLASS_H
#define ACLASS_H
#include "problemclass.h"
class AClass : public Base
{
public:
void DoSomething(ProblemClass* problem);
};
#endif
L'erreur de compilation se produit au niveau de la variable vide Dosomething ();
Je suis conscient que le code ici n'est pas suffisant pour résoudre le problème. J'ai été incapable de créer un exemple minimal capable de le reproduire. Ma question est donc beaucoup plus générale. Quel genre de choses pourrait causer cela? Y a-t-il quelque chose en particulier que je devrais rechercher ou une piste d'enquête que je devrais suivre pour le retrouver?
Ce code compile bien dans une version presque identique du projet.
Toute aide, quelle qu'elle soit, serait grandement appréciée. J'utilise codeblocks 10.05 avec mingw4.4.1 in win 7 64 bit.
Vous semblez dire que le code que vous affichez ne génère pas l'erreur du compilateur avec laquelle vous rencontrez un problème. Donc, nous ne pouvons que deviner. Voici quelques possibilités:
J'ai eu ce même message d'erreur à la suite d'une circulaire dependency dans mes fichiers/classes d'en-tête:
foo.hpp:
#ifndef FOO_HPP
#define FOO_HPP
#include <stdio.h>
#include "bar.hpp" // <-- here
class Foo {
public:
int value = 0;
void do_foo(Bar myBar) {
printf("foo + %d\n", myBar.value);
}
};
#endif //FOO_HPP
bar.hpp:
#ifndef BAR_HPP
#define BAR_HPP
#include <stdio.h>
#include "foo.hpp" // <-- and here
class Bar {
public:
int value = 1;
void do_bar(Foo myFoo) {
printf("bar = %d \n", myFoo.value);
}
};
#endif //BAR_HPP
La compilation avec: g++ -std=c++11 foo.hpp -o foo
a généré le résultat suivant:
In file included from foo.hpp:5:0:
bar.hpp:11:15: error: ‘Foo’ has not been declared
bar.hpp: In member function ‘void Bar::do_bar(int)’:
bar.hpp:12:32: error: request for member ‘value’ in ‘myFoo’, which is of non-class type ‘int’
Veuillez poster la commande que vous utilisez pour la compilation. J'ai vu ce problème si vous avez 2 fichiers distincts qui incluent le même en-tête et que vous faites un gcc * .cpp. Cela se produit parce que #define est défini pour toute l'instance de gcc et pas seulement pour chaque fichier objet compilé.
Ex.
Fichier1
#ifndef FILE1_HPP
#define FILE1_HPP 1
....
#endif
Ensuite, deux fichiers distincts qui le référencent.
#include <file1.hpp>
Si vous essayez de tout compiler en même temps, l'un des fichiers cpp échouera puisque FILE1_HPP était déjà défini (le fichier d'en-tête est donc ignoré pour ce fichier cpp).
gcc -Wall *.cpp
La solution consiste à supprimer le #ifndef ou à compiler chaque fichier dans ses propres fichiers objet, puis à les lier à votre application principale.
J'ai rencontré un problème similaire et il m'a fallu un certain temps pour savoir pourquoi.
Dans votre cas, vous pouvez définir PROBLEMCLASS_H dans d’autres fichiers d’en-tête. La conséquence est que votre fichier cpp ignorera la définition dans le fichier d’en-tête. En d'autres termes, la ligne #include "problemclass.h"
est ignorée.
Dans mon cas, j'utilise MingW64 sous Linux. Disons que j'ai un fichier d'en-tête IO.h:
// IO.h
#ifndef _IO_H_
#define _IO_H_
class A{
...
};
#endif
Dans mon fichier main.cpp:
// main.cpp
#include <unistd.h>
#include "IO.h"
int main(int argc, char** argv) {
//...
}
Le fichier cpp a l'air innocent. Cependant, lorsque unistd.h
est inclus, il inclut secrètement /usr/i686-w64-mingw32.static/include/io.h
fourni par MingW, et ce io.h
ressemble à ceci:
// io.h
#ifndef _IO_H_
#define _IO_H_
...
#endif /* End _IO_H_ */
Vous pouvez maintenant voir que l'inclusion de unistd.h
mènera à l'inclusion io.h
de MingW et que cela masquera mon propre IO.h. Je suppose que c'est un problème similaire au vôtre.
Si vous changez l'ordre des inclusions (mettez #include <unistd.h>
après IO.h), le programme est compilé. Mais ce n'est pas une bonne suggestion. Je vous recommande de ne pas utiliser _IO_H_ pour protéger votre propre IO.h.
Pour comprendre comment/pourquoi votre PROBLEMCLASS_H
est inclus, je souscris à @greatwolf, vous pouvez utiliser g++ -E
pour générer la sortie du préprocesseur et l'examiner manuellement. Vérifiez quels fichiers sont inclus avant votre PROBLEMCLASS_H
et dans quel ordre ils sont inclus. J'espère que cela peut aider à résoudre votre problème.
À tous ceux qui voient ce message et qui ont cette erreur, je tiens à signaler que cela m’arrive fréquemment lorsque j’oublie d’ajouter le spécificateur de classe avant un nom de fonction, cette fonction utilisant un élément défini en privé dans l’en-tête de la classe.
PAR EXEMPLE:
Entête
class SomeClass
{
public:
void SomeFunc();
private:
typedef int SomeType_t;
};
Source (Lance une erreur SomeType_t n'est pas défini )
void SomeFunc()
{
SomeType_t dummy = 0;
}
Source (Fixe)
void SomeClass::SomeFunc()
{
SomeType_t dummy = 0;
}
C'est une erreur stupide, mais très facile à faire et à ne pas voir avant que vous ne vous soyez donné trois commotions en vous frappant la tête contre le bureau.
La seule chose à laquelle je pourrais penser qui pourrait causer l’erreur de compilation basée sur ce que vous avez présenté est si PROBLEMCLASS_H
a été redéfini en quelque sorte en dehors du fichier d’en-tête. Comme par exemple:
//main.cpp
#define PROBLEMCLASS_H
#include "aclass.h"
int main() {}
Une idée que vous pouvez essayer est de ne pas inclure 'problemclass.h' dans 'aclass.h' mais de simplement faire une déclaration de ProblemClass
à la place. Pour que cela fonctionne, vous devez vous assurer que la définition de AClass
ne contient que des références ou des pointeurs vers ProblemClass
- vous ne voulez pas que le compilateur essaie de prendre la taille de ProblemClass
qui aurait besoin de sa définition complète.
//aclass.h
#ifndef ACLASS_H
#define ACLASS_H
class ProblemClass;
class AClass : public Base
{
public:
void DoSomething(ProblemClass* problem);
};
#endif
Une autre technique que vous pouvez utiliser pour résoudre ce problème d’en-tête consiste à pré-traiter simplement l’unité de compilation «.cpp» qui pose problème. Ouvrez le fichier de sortie prétraité (généralement l'extension «.i») et inspectez ce qui se passe réellement. C'est pratique, surtout si les "inclus" sont nombreux et difficiles à prévoir.
J'ai eu le même problème et j'ai découvert ce que je faisais mal: en suivant votre exemple, j'ai inclus ProblemClass dans AClass, ce qui pose problème.