2010-12-13 3 views
1

J'ai un problème avec les définitions de mes classes, probablement à cause de l'ordre d'inclusion ou something.the msg d'erreur que je reçois estproblème avec l'inclusion d'en-tête d'une classe utilisée en tant que membre dans une autre classe C++

g++ -I/opt/PDmesa/Mesa-5.0.1/include -I/opt/PDmesa/GLUT-3.7/include -c test.cpp 
In file included from prog.h:16, 
       from test.cpp:10: 
repeat.h:21: error: ‘Prog’ does not name a type 
repeat.h:27: error: ‘Prog’ has not been declared 
repeat.h: In constructor ‘Repeat::Repeat(float)’: 
repeat.h:34: error: ‘in’ was not declared in this scope 
repeat.h:34: error: ‘pg’ was not declared in this scope 
repeat.h: In member function ‘virtual void Repeat::Run()’: 
repeat.h:44: error: ‘class Repeat’ has no member named ‘pg’ 
make: *** [test.o] Error 1 
% 

donc la question que dois-je faire pour que je puisse utiliser mes deux cours? main.cpp

#include <iostream> 
#include <fstream> 
#include <string> 
#include <vector> 
#include <cstdlib> 
#include <sstream> 
#include <iterator> 
#include "prog.h" 
#include "window.h" 


using namespace std; 

Prog Turtle; 

void draw(void) 
{ 
    Turtle.Run(); 
} 


int main (int argc, char** argv) // Create Main Function For Bringing It All Together 
{ 
    filebuf fb; 
    fb.open (argv[1],ios::in); 
    istream input(&fb); 
    input>>Turtle; 
    fb.close(); 
    window w(argc,argv); 
} 

prog.h

#ifndef PROG_H 
#define PROG_H 

#include <iostream> 
#include <fstream> 
#include <string> 
#include <vector> 
#include <cstdlib> 
#include <sstream> 
#include <iterator> 
#include "forward.h" 
#include "left.h" 
#include "right.h" 
#include "jump.h" 
#include "repeat.h" 

using namespace std; 

class Prog 
{ 
    private: 

    public: 
     Prog(); 
     ~Prog(); 
     void Run(); 
     void clearbuff(); 
     vector<node*> listing; 
     friend istream& operator>> (istream& in, Prog& pro); 
}; 


Prog::Prog() 
{ 
                    //Default constructor 
} 

Prog::~Prog() 
{ 
                    //Default destructor 
} 

void Prog::Run() 
{ 
    size_t sz=this->listing.size(); 
    for (size_t it=0;it<sz;it++) 
      { 
       node* ptr = this->listing.at(it); 
       ptr->Run(); 
      } 
} 

void Prog::clearbuff() 
{ 
    size_t sz=this->listing.size(); 
    for (size_t it=0;it<sz;it++) 
      { 
       node* ptr = this->listing.at(it); 
       delete ptr; 
      } 
} 

istream& operator>> (istream& in, Prog& pro) 
{ 
    string tmp, command; 
    double value; 
    vector<string> text; 
    while (in>>tmp) 
    { 
     for (size_t i=0;i!=tmp.size()+1;++i) 
      tmp[i]=toupper(tmp[i]); 
     text.push_back(tmp); 
    } 
    while (!text.empty()) 
    { 
     command=text[0]; 
     istringstream inpStream(text[1]); 
     float value = 0.0; 
     if ((inpStream >> value)&&!text.empty()) 
     { 
      if (command=="REPEAT") 
       { 
       unsigned int x(1), y(0), i(1), pos (0); 
       text.erase (text.begin(), text.begin()+2); 
       vector<string> reptext; 
       if (text[0]=="[") 
       { 
        for (i=1;(x!=y)&&i<=text.size();i++) 
         { 
          if (text[i]=="[") 
           ++x; 
          else if (text[i]=="]") 
           ++y; 
          reptext.push_back(text[i]); 
          pos=i; 
          } 
        reptext.erase(reptext.begin()+pos-1,reptext.end()); 
        ofstream tempfile ("output.txt"); 
        for(i=0; i<reptext.size(); i++) 
        tempfile << reptext[i] << endl; 
        tempfile.close(); 
        filebuf rfb;   
        rfb.open ("output.txt",ios::in); 
        istream rin(&rfb); 
        pro.listing.push_back(new Repeat(value)); 
        Prog ptm; 
        rin>>ptm; 
        rfb.close(); 
        text.erase (text.end()); 
        text.erase (text.begin(), text.begin()+3); 
       } 
       else 
       cout << "not a bracket found after repeat command --problemo"; 
       } 
      else if (command=="FORWARD") 
       { 
        pro.listing.push_back(new Forward(value)); 
        text.erase (text.begin(), text.begin()+2); 
       } 
      else if (command=="LEFT") 
       { 
        pro.listing.push_back(new Left(value)); 
        text.erase (text.begin(), text.begin()+2); 
       } 
      else if (command=="RIGHT") 
       { 
        pro.listing.push_back(new Right(value)); 
        text.erase (text.begin(), text.begin()+2); 
       } 
      else if (command=="JUMP") 
       { 
        pro.listing.push_back(new Jump(value)); 
        text.erase (text.begin(), text.begin()+2); 
       } 
      else 
       cout << "Unknown command found in the input file!"; 
      // text.erase(text.begin()); 
     } 
     else 
     { 
      cout << " Value after command was not numeric or end of input file was reached!"; 
     } 
    } 
return in; 
} 

#endif // PROG_H 

repeat.h

#ifndef REPEAT_H 
#define REPEAT_H 

#include <iostream> 
#include <fstream> 
#include <string> 
#include <vector> 
#include <cstdlib> 
#include <sstream> 
#include <iterator> 
#include "command.h" 
#include "prog.h" 

using namespace std; 

class Repeat : public command 
{ 
    private: 
     Prog pg; 
     float repval; 
    public: 
     Repeat(float value); 
     ~Repeat(); 
     void Run(); 
     friend istream& operator>> (istream& in, Prog& pro); 
}; 

Repeat::Repeat(float value) : command(value) 
{ 
     this->repval=value; 

     for (int i=0;i<value;++i) 
      in>>pg; //ctor 
} 

Repeat::~Repeat() 
{ 

} 

void Repeat::Run() 
{ 
     this->pg.Run(); 
} 

#endif // REPEAT_H 

bonjour j'ajouté Cpp pour chaque en-tête qui a besoin d'un. maintenant je reçois l'erreur suivante

% make -f makefile3 
g++ -I/opt/PDmesa/Mesa-5.0.1/include -I/opt/PDmesa/GLUT-3.7/include -c test.cpp 
g++ -c forward.cpp 
g++ -c left.cpp 
g++ -c right.cpp 
g++ -c jump.cpp 
g++ -c repeat.cpp 
g++ -c prog.cpp 
g++ test.o -L/opt/PDmesa/Mesa-5.0.1/lib -L/opt/PDmesa/GLUT-3.7/lib -L/usr/X11R6/lib -lglut -lGLU -lGL -lX11 -lXext -lXmu -lXi -lm -o test 
test.o: In function `draw()': 
test.cpp:(.text+0x2ad): undefined reference to `Prog::Run()' 
test.o: In function `main': 
test.cpp:(.text+0x33a): undefined reference to `operator>>(std::basic_istream<char, std::char_traits<char> >&, Prog&)' 
test.o: In function `__static_initialization_and_destruction_0(int, int)': 
test.cpp:(.text+0x443): undefined reference to `Prog::Prog()' 
test.cpp:(.text+0x448): undefined reference to `Prog::~Prog()' 
collect2: ld returned 1 exit status 
make: *** [test] Error 1 

test.cpp

#include <iostream> 
#include <fstream> 
#include <sstream> 
#include "prog.h" 
#include "window.h" 
using namespace std; 

Prog Turtle; 

void draw(void) 
{ 
    Turtle.Run(); 
// Turtle.clearbuff(); 
} 


int main (int argc, char** argv) // Create Main Function For Bringing It All Together 
{ 
    filebuf fb; 
    fb.open (argv[1],ios::in); 
    istream input(&fb); 
    input>>Turtle; 
    fb.close(); 
    window w(argc,argv); 
} 

prog.cpp

#include "prog.h" 
#include <iostream> 
#include <fstream> 
#include <string> 
#include <vector> 
#include <sstream> 
#include <iterator> 
#include "forward.h" 
#include "left.h" 
#include "right.h" 
#include "jump.h" 
#include "repeat.h" 

Prog::Prog() 
{ 

} 

Prog::~Prog() 
{ 

} 

void Prog::Run() 
{ 
    size_t sz=this->listing.size(); 
    for (size_t it=0;it<sz;it++) 
      { 
       node* ptr = this->listing.at(it); 
       ptr->Run(); 
      } 
} 

void Prog::clearbuff() 
{ 
    size_t sz=this->listing.size(); 
    for (size_t it=0;it<sz;it++) 
      { 
       node* ptr = this->listing.at(it); 
       delete ptr; 
      } 
} 

istream& operator>> (istream& in, Prog& pro) 
{ 
    string tmp, command; 
    double value; 
    vector<string> text; 
    while (in>>tmp) 
    { 
     for (size_t i=0;i!=tmp.size()+1;++i) 
      tmp[i]=toupper(tmp[i]); 
     text.push_back(tmp); 
    } 
    while (!text.empty()) 
    { 
     command=text[0]; 
     istringstream inpStream(text[1]); 
     float value = 0.0; 
     if ((inpStream >> value)&&!text.empty()) 
     { 
      if (command=="REPEAT") 
       { 
       unsigned int x(1), y(0), i(1), pos (0); 
       text.erase (text.begin(), text.begin()+2); 
       vector<string> reptext; 
       if (text[0]=="[") 
       { 
        for (i=1;(x!=y)&&i<=text.size();i++) 
         { 
          if (text[i]=="[") 
           ++x; 
          else if (text[i]=="]") 
           ++y; 
          reptext.push_back(text[i]); 
          pos=i; 
          } 
        reptext.erase(reptext.begin()+pos-1,reptext.end()); 
        ofstream tempfile ("output.txt"); 
        for(i=0; i<reptext.size(); i++) 
        tempfile << reptext[i] << endl; 
        tempfile.close(); 
        filebuf rfb;   
        rfb.open ("output.txt",ios::in); 
        istream rin(&rfb); 
        //pro.listing.push_back(new Repeat(value,rin)); 
        Prog ptm; 
        rin>>ptm; 
        rfb.close(); 
        for (int rp=0;rp<value;rp++) 
         { 
          cout << rp << endl; 
          for (i=0;i<ptm.listing.size();i++) 
           pro.listing.push_back(ptm.listing.at(i)); 
         } 
        text.erase (text.end()); 
        text.erase (text.begin(), text.begin()+3); 
       } 
       else 
       cout << "not a bracket found after repeat command --problemo"; 
       } 
      else if (command=="FORWARD") 
       { 
        pro.listing.push_back(new Forward(value)); 
        text.erase (text.begin(), text.begin()+2); 
       } 
      else if (command=="LEFT") 
       { 
        pro.listing.push_back(new Left(value)); 
        text.erase (text.begin(), text.begin()+2); 
       } 
      else if (command=="RIGHT") 
       { 
        pro.listing.push_back(new Right(value)); 
        text.erase (text.begin(), text.begin()+2); 
       } 
      else if (command=="JUMP") 
       { 
        pro.listing.push_back(new Jump(value)); 
        text.erase (text.begin(), text.begin()+2); 
       } 
      else 
       cout << "Unknown command found in the input file!"; 
      // text.erase(text.begin()); 
     } 
     else 
     { 
      cout << " Value after command was not numeric or end of input file was reached!"; 
     } 
    } 
return in; 
} 

prog.h

#ifndef PROG_H 
#define PROG_H 

#include <iostream> 
#include <fstream> 
#include <vector> 
#include "node.h" 
using namespace std; 

class Repeat; 

class Prog 
{ 
    private: 

    public: 
     Prog(); 
     ~Prog(); 
     void Run(); 
     void clearbuff(); 
     friend istream& operator>> (istream& in, Prog& pro); 
     vector<node*> listing; 
}; 

#endif // PROG_H 

repeat.cpp

#include "repeat.h" 
using namespace std; 

Repeat::Repeat(float value, istream in) : command(value) 
{ 
     this->repval=value; 
     for (int i=0;i<value;++i) 
      in>>pg; //ctor 
} 

Repeat::~Repeat() 
{ 

} 

void Repeat::Run() 
{ 
     this-> pg.Run(); 
} 

repeat.h

#ifndef REPEAT_H 
#define REPEAT_H 

#include <iostream> 
#include <fstream> 
#include "command.h" 
#include "prog.h" 
using namespace std; 

class Prog; 

class Repeat : public command 
{ 
    private: 
     Prog pg; 
     float repval; 
    public: 
     Repeat(float value, istream in); 
     ~Repeat(); 
     void Run(); 
     friend istream& operator>> (istream& in, Prog& pro); 
}; 

#endif // REPEAT_H 

si je retire #include "prog.h" et toutes les références à Prog de test, il compile correctement, mais il ne marche pas réellement. aussi ce que je veux vraiment faire est de décommenter pro.listing.push_back(new Repeat(value,rin)); de prog.cpp et de supprimer les 10 prochaines lignes.Cette ligne était le problème avec la conception précédente. Je supsect que Im faisant encore quelque chose de mal avec toute la chose en-tête

Répondre

2

En prog.h vous incluez repeat.h en haut du fichier.

Le corps repeat.h ne voit aucune des définitions Prog.h.

Essayez d'avoir main.cpp comprennent repeat.h directement Supprimer #include « repeat.h » de prog.h

+0

J'ai mis #include "repeat.h" dans main et l'ai retiré de prog.h mais le même problème est survenu :( – pmantz

+0

J'espère que vous avez enlevé #include "prog.h" de main.cpp. Quand je fais ceci, c'est que le constructeur Repeat :: Repeat (float) essaye d'utiliser dans lequel il n'est pas défini – DanS

+0

Ce n'est pas vraiment un problème si vous mettez des choses dans des fichiers d'implémentation et de définition séparés - après tout si vous utilisez Tout doit aller dans l'en-tête Il peut être bon goût et le style de faire cela.Vous devez obtenir la commande d'inclusion à droite – DanS

3

Le problème ici est que vous avez des références circulaires.

Vous pouvez considérer une instruction #include comme simplement couper et coller le contenu de ce fichier dans le fichier où la directive est placée. Il y a plusieurs choses que vous pouvez faire.

# 1 - Mettez votre implémentation dans un fichier '.cpp'

Votre définition de classe 'Prog' ne mentionne pas Repeat. Si vous aviez un fichier 'prog.cpp' avec les définitions de méthodes réelles, vous pourriez y trouver et vous n'auriez aucun problème.

Autres astuces comprennent des déclarations vers l'avant, en utilisant des pointeurs dans votre defenition de classe où une référence circulaire doit avoir lieu, etc.

3
  1. Vous implémentez les fonctions membres pour vos classes dans les fichiers d'en-tête. Ne fais pas ça. Voilà à quoi servent les fichiers .cpp.

  2. Vous avez une inclusion circulaire. prog.h tente de #include "repeat.h" et repeat.h tente de #include "prog.h". L'un d'entre eux sera traité avant l'autre, et les gardes d'en-tête empêcheront le traitement de l'autre. L'effet net est que vous ne finissez pas #include tout ce que vous attendiez, et vous avez des déclarations manquantes.

C'est facile de fixer une fois que nous fixons le premier problème, parce que nous ne aurons plus besoin de savoir sur Repeat dans l'en-tête Prog, et peut tout simplement supprimer cette #include déclaration. Dans le fichier .cpp, nous incluons les deux en-têtes, et il n'y a pas de problème.

Je voudrais également vous référer à http://www.gamedev.net/reference/articles/article1798.asp qui explique tous les problèmes communs avec les fichiers d'en-tête et d'implémentation en détail.

1

Je peux ajouter que si la déclaration des deux classes se référencent mutuellement pour déplacer les implémentations vers des fichiers * .cpp ne serait pas vraiment utile (bien que cela soit toujours nécessaire), alors vous auriez dû utiliser des déclarations anticipées. comme ceci:

// in repeat.h 
class Prog; 
... 
friend istream& operator>> (istream& in, Prog& pro); 

// in prog.h 
class Repeat; 
... 
void someMethodThatUsesRepeat(Repeat *rep); 

Notez que même si vous n'avez pas deux classes faisant référence à l'autre, en utilisant l'avant les déclarations peuvent encore être utiles pour accélérer la compilation car le compilateur ne doit compiler les deux têtes chaque fois que repeat.h est inclus.

Questions connexes