C++循环中的包含关系

7
请考虑以下三个简化文件:
student.h:
#ifndef STUDENT_H
#define STUDENT_H

#include "course.h"

class Student
{
private:
    Course someCourse;
};

#endif

course.h:

#ifndef COURSE_H
#define COURSE_H

#include "student.h"

class Course
{
private:
    Student someStudent;
};

#endif

和 main.cpp 文件:

#include "student.h"
int main();

这不会编译,会提示错误C2146:缺少“;”的语法错误,标识符为'someStudent'。在更复杂的程序中,它会产生更多的错误(即使对于正确的代码部分也是如此)。我想设计可能有问题:Student 包含 CourseCourse 包含 Student。我的意图是表示一个学生参加多门课程,而一门课程有多个学生(在完整的程序中使用向量,在这里简化了)。您有什么建议吗?
Vlad,提前谢谢。 更新: 感谢快速回复。在Course类中提前声明Student类(并删除#include "student.h")似乎可以解决问题。 抱歉,我认为这里无关紧要,但事实上我在每个类中都使用常量指针的向量(因为一个学生不应该能够控制一门Course,而一门Course也不应该能够控制一个Student)。
vector<const Student* const> students; // in Course class

可能是C++中的循环依赖的重复问题。 - tenfour
4个回答

19
这是一个循环依赖的问题。只要你将StudentCourse类的非指针成员someStudentsomeCourse声明为非指针类型,编译器就会看到Student的定义,从而需要知道它的大小,这又意味着需要知道它所有成员的大小,包括其中的Course。然而,为了知道Course的大小,编译器又需要知道Student的大小。这就形成了循环依赖。 因此,你需要通过将它们中的至少一个声明为指针来打破这个循环依赖。例如,你可以这样做:
#ifndef STUDENT_H
#define STUDENT_H

//#include "course.h" //commenting out, as it is not needed!

class Course; //this is called forward declaration

class Student
{
private:
    Course *pSomeCourse; //pointer
};

#endif

还要注意的是,当你将pSomeCourse声明为Course*类型的指针时,你不需要包含定义Course的头文件。只需要对Course类进行前向声明就足够了,就像我在上面的代码中所做的那样。

它可以工作的原因是任何类的指针大小相同,编译器不需要知道类的大小,只需要知道同一类的指针大小即可。换句话说,编译器可以在不知道Course的大小的情况下,仅仅通过知道Course*的大小来知道sizeof(Course*)


4
除了Nawaz的答案之外:
如果你想从Student的成员访问Course的成员,你需要在定义Student方法的.cpp文件中包含Course.h。
否则,使用g++会出现“invalid use of incomplete type”的错误提示。

1
如果您想要链接两个类,您将需要使用前向声明和指向一个类接口中声明的类型实例的指针。另一个接口可以保持不变,只要它包含成员变量类型接口的声明即可。

course.h:

#ifndef COURSE_H
#define COURSE_H


class Student;
class Course
{
private:
    Student* someStudent;
};

#endif

student.h:

#ifndef STUDENT_H
#define STUDENT_H

#include "course.h"

class Student
{
private:
    Course someCourse;
};

#endif

0

你不能这样做,你必须将它们中的至少一个转换为指针。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接