在另一个类C ++中用作成员的类的头包含问题

时间:2010-12-13 13:16:28

标签: c++ class header include declaration

我的课程定义有问题,可能是因为包含顺序或其他原因。我收到的错误信息是

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行。这一行是以前设计的问题。我认为我再次做了整个标题的错误

4 个答案:

答案 0 :(得分:3)

这里的问题是你有循环引用。

您可以将#include语句视为简单地将该文件的内容剪切并粘贴到放置该指令的文件中。你可以做几件事。

#1 - 将您的实施放在'.cpp'文件中

您的“Prog”类定义未提及Repeat。如果你有一个带有实际方法定义的'prog.cpp'文件,你可以#include "repeat.h"那里,你就不会有任何问题。

其他技巧包括前向声明,使用类防御中的指针,需要进行循环引用等。

答案 1 :(得分:3)

  1. 您正在头文件中实现类的成员函数。 不要这样做。这就是.cpp文件的用途。

  2. 您有一个循环包含。 prog.h尝试#include "repeat.h",并且repeat.h尝试#include "prog.h"。其中一个将在另一个之前处理,然后标题保护将阻止另一个处理。最终效果是你没有#include你所期望的一切,然后你遗漏了声明。

  3. 修复第一个问题后,这很容易解决,因为我们将不再需要知道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>