Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Includes in a cycle

Tags:

c++

include

cycle

Please consider the following three simplified files:
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

and main.cpp:

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


This wouldn't compile giving me
error C2146: syntax error : missing ';' before identifier 'someStudent'

It would produce a lot more errors (even for the correct portions of code) in a more complicated program. I guess the design is wrong: Student includes Course and Course includes Student. What I want to represent with it is that a student takes several courses and a course has has several students (I use vectors in a full program, avoided them here for simplicity). Any advice how this would be possible?

Thanks in advance, Vlad.

UPDATE: Thanks for fast replies. Forward declaration of Student class in Course class (and removing #include "student.h") seems to do the job. Sorry, I thought it wouldn't matter here, but in fact I am using vectors of const pointers in each of them (since a Student shouldn't be able to control a Course and a Course shouldn't be able to control a Student), as:

vector<const Student* const> students; // in Course class
like image 978
Vlad Avatar asked Oct 08 '11 09:10

Vlad


People also ask

When to include header files in c++?

A header file should be included only when a forward declaration would not do the job. The header file should be so designed that the order of header file inclusion is not important. The header file inclusion mechanism should be tolerant to duplicate header file inclusions.

Does header file need include?

Such project header files should contain #include statements for the system headers; if the body includes them first, the compiler does not check this.

HOW include all header files in C++?

You make the declarations in a header file, then use the #include directive in every . cpp file or other header file that requires that declaration. The #include directive inserts a copy of the header file directly into the . cpp file prior to compilation.

Which is the header that should be included first in C++?

cpp should include source1. h before including anything else.


3 Answers

This is going circular, as long as you declare someCourse and someStudent as non-pointer members of class Student and Course respectively (as you've done), because the compiler sees the definition of Student, it needs to know its size which in turn means, it needs to know the size of its all members, including Course which is one of them. But to know the size of Course, it needs to know the size of Student. That becomes circular.

So you need to break this circle, by declaring at least one of them as pointer. For example, you can do this:

#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

Also note that when you declare pSomeCourse as pointer of type Course*, you don't need to include the header file in which Course is defined. Just forward declaration of the class Course is enough, as I did in the above code.

The reason why it works because the size of pointer of any class is same, and the compiler need not know the size of the class, in order to know the size of the pointer of the same class. In other words, the compile can know sizeof(Course*) without even knowing sizeof(Course).

like image 172
Nawaz Avatar answered Nov 04 '22 05:11

Nawaz


In addition to Nawaz answer:

if you want to access members of Course from members of Student, you need to include Course.h in the .cpp - File where you define the methods of Student.

With g++ you'll get an error like "invalid use of incomplete type" otherwise.

like image 39
Max Avatar answered Nov 04 '22 03:11

Max


If you want to link two classes you will have to use forward declaration and a pointer to an instance of the declared type in one of the class interfaces. Another interface can stay the same as long as it includes declaration of the member variable's type interface.

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
like image 40
justadreamer Avatar answered Nov 04 '22 03:11

justadreamer