0

我的搜索使我相信我遇到的问题称为循环冗余。我不明白发布的任何解决方案。我(相当)是 C++ 新手,来自强大的 Java 背景。

基本上有两个相互依赖的类。A 类包含 B 类对象的向量,B 类包含需要 A 类对象作为输入的方法。

这是重现问题的代码。

根据codelite g++,错误在school.h中并且是“人没有在这个范围内声明”。它还说“模板参数 1 无效”和“模板参数 2 无效”。然后是其他几个,关于所有被调用的向量函数的非类类型“int”。

主文件

#include <iostream>
#include <string>
#include "person.h"
#include "school.h"

int main() {
    person p;   
    school s;
    std::cout << p.name << std::endl;
    s.personVect.push_back(p);
    std::cout << s.personVect.size() << std::endl;
    std::cout << s.personVect.at(0).name << std::endl;
    p.test();
    return 0;
}

学校.h

#ifndef SCHOOL_H
#define SCHOOL_H
#include <vector>
#include "person.h"

class school
{
public:
    school();
    ~school();

    std::vector<person> personVect;


};

#endif // SCHOOL_H

学校.cpp

#include "school.h"    
school::school(){}    
school::~school(){}

人.h

#ifndef PERSON_H
#define PERSON_H
#include <string>
#include <vector>
#include "school.h"


class person {
public:

    std::string name;
    std::string phone;

    school doSomethingWithSchool();

    void test();

    person();
    ~person();

};

#endif // PERSON_H

个人.cpp

#include "person.h"
#include <iostream>
using namespace std;

person::person()
{
    name = "marcus";
    phone = "0400000000";
}

person::~person()
{
}

void person::test() {
    cout << this->name;
}
school person::doSomethingWithSchool() {
    school s; 
}
4

4 回答 4

2

这个问题可以通过更好地设计你的类关系来解决。

APerson不是由 a 组成的School,因此它不需要有 School 成员。

ASchool有一组Person对象。

如果您希望一个人与学校做某事,请将其作为参数传递。这样,您可以使用指针前向声明来解决问题。

// Person.h
class School; // Forward declare school type.

// Person.cpp
Person::DoSomethingWithSchool(School* school);
于 2013-03-28T06:21:23.557 回答
0

您的问题在于 school.h 有一个 #include "person.h" 语句,而 person.h 有一个 #include "school.h" 语句。

解决方案

school课堂上vector<person>,使用. 而不是vector<person*>. 不要在此处包含 person.h,而是添加语句class person;。假设您的school班级最终会以某种方式修改person对象,请将 放在#include person.h您的 school.cpp 文件中,在语句之后#include school.h

错误解释

这是编译时发生的事情的逐步细分:

  1. 在 main.cpp 中,您首先包含 person.h。预处理器找到 person.h。由于您以前从未包含过它,因此尚未定义 PERSON_H 并且 ifndef PERSON_H 当前为真。所以我们转到文件的下一行。

  2. 在这个文件中发生的第一件有趣的事情是 PERSON_H 被定义(#fdefine PERSON_H)。下次你#include这个文件时,预处理器将跳过整个文件,直接到#endif。

  3. 发生的第二件有趣的事情是 school.h 被包含在内。所以预处理器找到了 school.h(我们还没有处理 School 类!),直到现在还没有被处理过。

  4. school.h 中第一个有趣的东西(在#define SCHOOL_H 之后)是#include person.h,所以预处理器返回到 person.h(我们还没有处理 Person 类!)。但是这一次,PERSON_H 已经定义了,所以#ifndef PERSON_H 为假,预处理器跳到那个文件中的#endif(正如我在(2)中提到的)。所以 Person 类仍然没有被声明。

  5. 我们回到school.h,什么也没做。此时,我们即将声明/定义学校类。从未声明过person 类,因为我们的预处理器从 person.h 跳转到 school.h 再到 person.h 再回到 school.h,只处理#include指令。

  6. 编译器开始遍历school类定义。下一个有趣的事情是线std::vector<person> personVect;。您已尝试实例化一个vector<person>. 但是person这里是未知的(即没有在这个范围内声明),因为(5)。这解释了您的两个模板参数错误: Avector<person>实际上是隐含的 a vector <person, allocator<person> >。第一个模板参数是person,第二个是allocator<person>。因为person是未知的,所以这两个论点都是无效的。

解决方案说明

school.h 包含 person.h,而 person.h 包含 school.h 的事实是导致您提到的循环依赖的原因。为了避免这种情况,我们需要另一种方式来声明我们将在文件中使用特定的类。常见的方法是使用前向声明——class person;我在解决方案中提到的声明,在school. 这是一个普通的声明,它让编译器知道person(在school类中使用)指的是一个类。

然而,为了构造vector<person>,编译器还需要知道类在内存中占用了多少空间person(即它的大小),而我们没有在声明中提供(并且永远无法手动提供)class person;。事实上,编译器只有在处理完头文件中的完整定义后才知道类的大小。但是,如果我们尝试这样做,我们又回到了原点(循环依赖,等等)。我们所知道的是指向 的指针的大小person,因为这是特定于机器的(例如,在 32 位机器上,指向任何东西的指针的大小都是 32 位)。因此,我们可以实例化 a,因为无论实际是vector<person*>什么,它始终是一个 32 位对象的向量。person

于 2013-03-28T07:07:44.483 回答
0

而不是#include "person.h"
在头文件(“school.h”)中包含人员,如果需要,只需编写class person;并使用指向person
And 在 C++ 模块(“school.cpp”)中包含“person.h”的指针。

这在功能上也会有一些好处。(减少编译时间)

有用的链接:

http://www.codeproject.com/Articles/547275/Whyplusisplusitplusbuildingplussopluslong-3f https://stackoverflow.com/a/553869/328260

于 2013-03-28T06:16:58.577 回答
0

尝试这个,

人.h

        #ifndef PERSON_H
        #define PERSON_H
        #include <string>
        #include <vector>

        class school;
        class person {
        public:

            std::string name;
            std::string phone;

            school doSomethingWithSchool();

            void test();

            person();
            ~person();

        };

        #endif // PERSON_H

学校.h

      #ifndef SCHOOL_H
      #define SCHOOL_H
      #include <vector>

      class person;
      class school
      {
      public:
          school();
          ~school();

          std::vector<person*> personVect;
      };

      #endif // SCHOOL_H

个人.cpp

    #include "person.h"
    #include "school.h"
    #include <iostream>
    using namespace std;

    person::person()
    {
        name = "marcus";
        phone = "0400000000";
    }

    person::~person()
    {
    }

    void person::test() {
        cout << this->name;
    }
    school person::doSomethingWithSchool() {
        school s; 
        return s;
    }

并在 main.cpp

    int main()
    {
        person *p = new person;   
        school s;
        std::cout << p->name << std::endl;
        s.personVect.push_back(p);
        std::cout << s.personVect.size() << std::endl;
        std::cout << s.personVect.at(0)->name << std::endl;
        p->test();
        delete p;
        return 0;
    }
于 2013-03-28T06:52:22.457 回答