C ++ класс не включен должным образом - PullRequest
1 голос
/ 26 апреля 2010

У меня есть проблема, которую я совершенно не понимаю или очень странная. Вероятно, это первый, но я потратил целый день на поиски безуспешно, так что вот так ...

У меня есть класс с именем Schedule, в качестве члена которого имеется вектор Room. Однако, когда я компилирую с использованием cmake или даже вручную, я получаю следующее:

In file included from schedule.cpp:1:
schedule.h:13: error: ‘Room’ was not declared in this scope
schedule.h:13: error: template argument 1 is invalid
schedule.h:13: error: template argument 2 is invalid
schedule.cpp: In constructor ‘Schedule::Schedule(int, int, int)’:
schedule.cpp:12: error: ‘Room’ was not declared in this scope
schedule.cpp:12: error: expected ‘;’ before ‘r’
schedule.cpp:13: error: request for member ‘push_back’ in ‘((Schedule*)this)->Schedule::_sched’, which is of non-class type ‘int’
schedule.cpp:13: error: ‘r’ was not declared in this scope

Вот соответствующие биты кода:

#include <vector>

#include "room.h"

class Schedule
{
  private:
    std::vector<Room> _sched; //line 13
    int _ndays;
    int _nrooms;
    int _ntslots;
  public:
    Schedule();
    ~Schedule();
    Schedule(int nrooms, int ndays, int ntslots);
};
Schedule::Schedule(int nrooms, int ndays, int ntslots):_ndays(ndays), _nrooms(nrooms),_ntslots(ntslots)
{
  for (int i=0; i<nrooms;i++)
  {
    Room r(ndays,ntslots);
    _sched.push_back(r);
  }
}

Теоретически, g ++ должен компилировать класс перед тем, который включает его. Здесь нет циклических зависимостей, это все просто. Я полностью озадачен этим, и это заставляет меня верить, что я что-то упускаю. : -D

Edit:
Содержание room.h из комментариев ниже:

#include <vector>  
#include "day.h" 

class Room 
{ 
private: 
   std::vector<Day> _days; 

public: 
   Room(); 
   Room(int ndays, int length); 
   ~Room(); 
};

Ответы [ 5 ]

4 голосов
/ 26 апреля 2010

Даже если вы пропустили какой-то важный код (а именно, содержимое day.h), мой психический отладчик говорит мне, что в ваших заголовочных файлах есть циклическая зависимость:

// schedule.h
#include "room.h"

// room.h
#include "day.h"

// day.h
#include "schedule.h"

Это плохо. Чтобы разорвать круговую зависимость, вам нужно выяснить, какой файл не должен знать конкретные детали реализации других. Это делается с использованием прямых ссылок. Например, я вижу, что вашему определению класса Room на самом деле не нужно знать, что такое sizeof(Day) для определения класса, поэтому вы можете переписать его следующим образом:

#include <vector>
// do NOT include day.h

class Day;  // forward declaration
class Room 
{ 
private: 
   std::vector<Day> _days; 

public: 
   Room(); 
   Room(int ndays, int length); 
   ~Room(); 
};

Теперь room.h не зависит от day.h, нарушая круговую зависимость. Конечно, файл реализации room.cpp все равно должен будет содержать day.h.

1 голос
/ 26 апреля 2010

Это может не иметь значения, но я не вижу в ваших заголовках охранников. Не должно иметь значения, но только чтобы покрыть любой угол ...

0 голосов
/ 26 апреля 2010

Как выглядит Room.cpp?

Кроме того ... У меня никогда не было проблем с этим, но, может быть, вы забыли добавить дополнительную строку внизу заголовочного файла?

0 голосов
/ 26 апреля 2010

Я не могу сказать из вашего поста schedule.h / .cpp, но похоже, что у вас есть #include "room.h" в schedule.cpp, но ваш schedule.h использует класс Room. #include "room.h" должно быть в schedule.h, если это так.

Или вы можете использовать предварительную декларацию в schedule.h.

0 голосов
/ 26 апреля 2010

Теоретически g ++ должен скомпилировать класс перед тем, который его включает.

g ++ должен иметь возможность компилировать ваши исходные файлы в любом порядке.Порядок, в котором включает заголовки в ваш источник, устанавливается в порядке ваших операторов #include.

Наиболее вероятный случай - имя класса room, а не Room.Следующим, вероятно, является то, что имя - это нечто другое, кроме Room.Менее вероятно, что оно находится в пространстве имен, отличном от корневого пространства имен.

РЕДАКТИРОВАТЬ: Хорошо, если это не так, убедитесь, что включается room.h, который является вашим room.h, а не некоторыедругое room.h.Ничего подобного редактированию неправильной копии файла, чтобы потратить впустую ваш день.

РЕДАКТИРОВАТЬ 2: Я предполагаю, что ваши заголовочные файлы имеют обычную структуру include-Once:

#ifndef schedule_h
#define schedule_h

// header file code goes here.

#endif

...и что вы опустите его для краткости.

РЕДАКТИРОВАТЬ 3: Я просто скопировал код, который вы дали в новый каталог, и создал фиктивный файл day.h с содержанием:

typedef int Day;

Затем я использовал g++ -c -o schedule.o schedule.cpp для его сборки и не получил ошибок.Поэтому ошибка - это то, чего мы не видим.

Редактировать 4: Хорошо, время проверки работоспособности.Посмотрите на верхнюю часть room.h и убедитесь, что там написано

#ifndef room_h

, а не

#ifdef room_h
...