我的课程定义有问题,可能是因为包含顺序或其他原因。我收到的错误信息是
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
%
所以问题我应该怎么做才能使用我的两个课程? 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
你好我为每个需要一个的头添加了单独的.cpp。现在我收到以下错误
% 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
如果我从test中删除#include "prog.h"
和所有对Prog的引用,它会正确编译,但它实际上并不起作用。我真正想做的是从prog.cpp取消注释pro.listing.push_back(new Repeat(value,rin));
并删除接下来的10行。这一行是以前设计的问题。我认为我再次做了整个标题的错误
答案 0 :(得分:3)
这里的问题是你有循环引用。
您可以将#include
语句视为简单地将该文件的内容剪切并粘贴到放置该指令的文件中。你可以做几件事。
#1 - 将您的实施放在'.cpp'文件中
您的“Prog”类定义未提及Repeat
。如果你有一个带有实际方法定义的'prog.cpp'文件,你可以#include "repeat.h"
那里,你就不会有任何问题。
其他技巧包括前向声明,使用类防御中的指针,需要进行循环引用等。
答案 1 :(得分:3)
您正在头文件中实现类的成员函数。 不要这样做。这就是.cpp文件的用途。
您有一个循环包含。 prog.h尝试#include "repeat.h"
,并且repeat.h尝试#include "prog.h"
。其中一个将在另一个之前处理,然后标题保护将阻止另一个处理。最终效果是你没有#include
你所期望的一切,然后你遗漏了声明。
修复第一个问题后,这很容易解决,因为我们将不再需要知道Repeat
标头中的Prog
,并且可以删除#include
语句。在.cpp文件中,我们包含两个标题,没有问题。
我还想推荐给http://www.gamedev.net/reference/articles/article1798.asp,它详细解释了标题与实现文件的所有常见问题。
答案 2 :(得分:2)
在prog.h中,您可以在文件顶部包含repeat.h。
body repeat.h没有看到任何Prog.h定义。
尝试直接使用main.cpp包含repeat.h 从prog.h中删除#include“repeat.h”
答案 3 :(得分:1)
我可以补充一点,如果两个类的声明相互引用,那么将实现移动到* .cpp文件实际上并没有帮助(虽然它仍然是必要的),那么你应该使用前向声明而不是包含,比如说这样:
// in repeat.h
class Prog;
...
friend istream& operator>> (istream& in, Prog& pro);
// in prog.h
class Repeat;
...
void someMethodThatUsesRepeat(Repeat *rep);
请注意,即使您没有两个引用彼此的类,使用前向声明可能仍然有助于加快编译速度,因为每次包含repeat.h时,编译器都不必编译两个头文件。 / p>