我的搜索让我相信我遇到的问题称为循环冗余。我不明白任何发布的解决方案。我(相当)是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;
}
答案 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文件中。
这是对编译时发生的情况的逐步细分:
在main.cpp中,首先包含person.h。预处理器去找人。由于您之前从未包含它,因此尚未定义PERSON_H且ifndef PERSON_H当前为true。所以我们转到文件的下一行。
此文件中发生的第一个有趣的事情是定义了PERSON_H(#include school.h
)。下次#fdefine PERSON_H
此文件时,预处理器将跳过整个文件,直到#endif。
第二次有趣的事情是school.h被包含在内。所以预处理器找到了school.h(我们还没有处理过School类!),直到现在还没有处理过。
school.h中的第一个有趣的事情(#define SCHOOL_H之后)是 #include person.h ,因此预处理器返回给人。 h(我们还没有处理Person类!)。但这一次,PERSON_H已经定义,所以#ifndef PERSON_H为false,预处理器跳转到该文件中的#endif(正如我在(2)中提到的那样)。所以Person类仍未被声明。
我们没有做任何事情就回到了学校。在这一点上,我们即将宣布/定义学校班级。 person类有从未被声明,因为我们的预处理器从person.h跳到school.h回到person.h回到school.h,只处理#include
指令。
编译器开始浏览#include
类定义。下一个有趣的事情是行school
。您试图实例化std::vector<person> personVect;
。但是vector<person>
因为(5)而未知(即未在此范围内声明)。这解释了您的两个模板参数错误:person
实际上隐式为vector<person>
。第一个模板参数是vector <person, allocator<person> >
,第二个是person
。由于allocator<person>
未知,因此这两个参数均无效。
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*>
实际上是什么。