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

一个类包含在另一类C++中作为成员的头包涵的问题,c++,class,header,include,declaration,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’ ha

我的类的定义有问题,可能是因为包含顺序或其他原因

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

程序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
#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
重复

#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
#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
您好,我为每个需要一个标题添加了单独的.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;
}
程序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
#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
重复.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();
}
重复

#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
#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

若我从测试中删除include prog.h和所有对prog的引用,它会正确编译,但实际上不起作用。另外,我实际上想做的是取消pro.listing.push_backnew Repeatvalue,rin;从prog.cpp中删除接下来的10行。这一行是以前设计的问题。我怀疑我在prog.h中的整个头部分又出了问题,你在文件顶部添加了repeat.h

主体repeat.h没有看到任何Prog.h定义

尝试直接让main.cpp包含repeat.h
从prog.h中删除include repeat.h在prog.h中,您可以在文件顶部包含repeat.h

主体repeat.h没有看到任何Prog.h定义

尝试直接让main.cpp包含repeat.h
从prog.h中删除include repeat.h这里的问题是您有循环引用

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

1-将实现放在“.cpp”文件中

您的“Prog”类定义没有提到Repeat。如果您有一个包含实际方法定义的“prog.cpp”文件,您可以在其中包含repeat.h,这样就不会有任何问题


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

这里的问题是您有循环引用

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

1-将实现放在“.cpp”文件中

您的“Prog”类定义没有提到Repeat。如果您有一个包含实际方法定义的“prog.cpp”文件,您可以在其中包含repeat.h,这样就不会有任何问题

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

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

你有一份通知。prog.h尝试包含repeat.h,repeat.h尝试包含prog.h。其中一个将在另一个之前被处理,然后收割台防护装置将阻止另一个被处理。最终的结果是,您没有包含您期望包含的所有内容,然后您就缺少了声明

一旦我们解决了第一个问题,这很容易解决,因为这样我们就不再需要知道Prog头中的Repeat,只需删除include语句即可。在.cpp文件中,我们同时包含了两个头,没有问题

我还想让您参考其中详细解释了头文件与实现文件的所有常见问题

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

你有一份通知。prog.h尝试包含repeat.h,repeat.h尝试包含prog.h。其中一个将在另一个之前被处理,然后收割台防护装置将阻止另一个被处理。最终的结果是,您没有包含您期望包含的所有内容,然后您就缺少了声明

一旦我们解决了第一个问题,这很容易解决,因为这样我们就不再需要知道Prog头中的Repeat,只需删除include语句即可。在.cpp文件中,我们同时包含了两个头,没有问题


我还想向您介绍一下,它详细解释了头文件与实现文件之间的所有常见问题。

我可以补充一点,如果两个类的声明都相互引用,那么将实现移动到*.cpp文件并没有真正的帮助,尽管这仍然是必要的,那么您应该使用前向声明而不是include,如下所示:

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

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

请注意,即使没有两个类相互引用,使用前向声明可能仍然有助于加快编译速度,因为当包含repeat.h时,编译器不必每次都编译这两个头。

我可以补充一点,如果两个类的声明都相互引用,那么将实现移动到*.cpp文件将不会有真正的帮助,尽管它仍然会 如果有必要,那么应该使用前向声明而不是include,如下所示:

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

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

请注意,即使没有两个类相互引用,使用前向声明可能仍然有助于加快编译速度,因为每次包含repeat.h时,编译器不必同时编译这两个头。

我将include repeat.h放在main中,并将其从prog.h中删除,但出现了相同的问题:我希望您已从main.cpp中删除include prog.h。当我这样做的时候出现的问题是,构造函数Repeat::Repeatfloat试图使用其中未定义的。是否将内容放在单独的实现和定义文件中并不是真正的问题——毕竟,如果使用的是模板,则所有内容都必须放在标题中。不过,这可能是一种很好的品味和风格。您需要获得正确的包含顺序。谢谢,我在main.cpp中仍然有include prog.h。我还通过将include repeat.h in prog.h移到istream&operator>>之前解决了它。istream&in,prog&pro定义并将include prog.h保留在main.cpp是的,通常有几种方法来解决这些问题。重复。h显然需要包括prog.h。不清楚为什么prog.h应该包括repeat.h。虽然这是允许的,风格警察会抱怨包括一半下来你的档案!我将include repeat.h放在main中,并将其从prog.h中删除,但出现了相同的问题:我希望您已经从main.cpp中删除了include prog.h。当我这样做的时候出现的问题是,构造函数Repeat::Repeatfloat试图使用其中未定义的。是否将内容放在单独的实现和定义文件中并不是真正的问题——毕竟,如果使用的是模板,则所有内容都必须放在标题中。不过,这可能是一种很好的品味和风格。您需要获得正确的包含顺序。谢谢,我在main.cpp中仍然有include prog.h。我还通过将include repeat.h in prog.h移到istream&operator>>之前解决了它。istream&in,prog&pro定义并将include prog.h保留在main.cpp是的,通常有几种方法来解决这些问题。重复。h显然需要包括prog.h。不清楚为什么prog.h应该包括repeat.h。虽然这是允许的,风格警察会抱怨包括一半下来你的档案!