C ++类相互依赖,导致循环依赖性错误

时间:2013-03-28 06:12:57

标签: c++ scope redundancy cyclic

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

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

这是重现问题的代码。

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

main.cpp

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

school.h

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

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

    std::vector<person> personVect;


};

#endif // SCHOOL_H

school.cpp

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

person.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

person.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 个答案:

答案 0 :(得分:3)

通过更好地设计类关系可以解决问题。

Person不是由School组成,因此不需要有学校成员。

School有一组Person个对象。

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

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

// Person.cpp
Person::DoSomethingWithSchool(School* school);

答案 1 :(得分:0)

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

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

有用的链接:

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

答案 2 :(得分:0)

试试这个,

person.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

school.h

      #ifndef SCHOOL_H
      #define SCHOOL_H
      #include <vector>

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

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

      #endif // SCHOOL_H

person.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;
    }

答案 3 :(得分:0)

你的问题在于school.h有一个#include“person.h”语句,而person.h有一个#include“school.h”语句。

解决方案

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

解释错误

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

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

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

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

  4. school.h中的第一个有趣的事情(#define SCHOOL_H之后)是 #include person.h ,因此预处理器返回给人。 h(我们还没有处理Person类!)。但这一次,PERSON_H已经定义,所以#ifndef PERSON_H为false,预处理器跳转到该文件中的#endif(正如我在(2)中提到的那样)。所以Person类仍未被声明。

  5. 我们没有做任何事情就回到了学校。在这一点上,我们即将宣布/定义学校班级。 person类有从未被声明,因为我们的预处理器从person.h跳到school.h回到person.h回到school.h,只处理#include指令。

  6. 编译器开始浏览#include类定义。下一个有趣的事情是行school。您试图实例化std::vector<person> personVect;。但是vector<person>因为(5)而未知(即未在此范围内声明)。这解释了您的两个模板参数错误:person实际上隐式为vector<person>。第一个模板参数是vector <person, allocator<person> >,第二个是person。由于allocator<person>未知,因此这两个参数均无效。

  7. 解决方案

    school.h包含person.h,person.h包含school.h,这是导致你提到的循环依赖的原因。为了避免这种情况,我们需要一种替代方法来声明我们将在文件中使用特定的类。常见的方法是在person的定义之前使用前向声明 - 我在解决方案中提到的语句class person;。这是一个普通的声明,让编译器知道school(在person类中使用)引用了一个类。

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