C ++ Включает в цикл - PullRequest
       13

C ++ Включает в цикл

3 голосов
/ 08 октября 2011

Пожалуйста, рассмотрите следующие три упрощенных файла:
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 включает Course и Course включает Student.Что я хочу изобразить, так это то, что студент проходит несколько курсов, а в курсе есть несколько студентов (я использую векторы в полной программе, избегая их здесь для простоты).Любой совет, как это было бы возможно?

Заранее спасибо, Влад.

ОБНОВЛЕНИЕ: Спасибо за быстрые ответы.Прямое объявление класса Student в классе Course (и удаление #include "student.h"), кажется, делает эту работу.Извините, я думал, что здесь это не имеет значения, но на самом деле я использую векторы константных указателей в каждом из них (поскольку ученик не должен иметь возможность контролировать Course, а Course не должен быть в состояниидля управления Student), как:

vector<const Student* const> students; // in Course class

Ответы [ 4 ]

13 голосов
/ 08 октября 2011

Это происходит по кругу, пока вы объявляете someCourse и someStudent как не указывающие члены класса Student и Course соответственно (как вы сделали), потому что компилятор видит определение 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, как я делал в приведенном выше коде.

Причина, по которой это работает, потому что размер указателя любого класса одинаков, и компилятору не нужно знать размер класса, чтобы узнать размер указателя того же класса. Другими словами, компилятор может знать sizeof(Course*), даже не зная sizeof(Course).

4 голосов
/ 25 января 2013

В дополнение к ответу Nawaz:

если вы хотите получить доступ к членам курса от участников Student, вам необходимо включить файл Course.h в .cpp - файл, в котором вы определяете методы Student.

С g ++ вы получите ошибку типа «недопустимое использование неполного типа» в противном случае.

1 голос
/ 08 октября 2011

Если вы хотите связать два класса, вам придется использовать предварительное объявление и указатель на экземпляр объявленного типа в одном из интерфейсов класса. Другой интерфейс может оставаться таким же, пока он включает объявление интерфейса типа переменной-члена.

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 голосов
/ 08 октября 2011

Вы не можете этого сделать, вам нужно преобразовать хотя бы один из них в указатель.

...