【问题标题】:C++ class is not being included properly没有正确包含 C++ 类
【发布时间】:2010-04-26 16:21:06
【问题描述】:

我有一个问题,要么是我完全无法理解,要么很奇怪。这可能是第一个,但我整个下午都在谷歌上搜索没有成功,所以这里......

我有一个名为 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

编辑:
room.h的内容来自以下cmets:

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

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

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

【问题讨论】:

  • room.h 是什么样的?房间等级是大写还是小写?
  • Room 是否在命名空间中定义?
  • 看起来像这样:#include #include "day.h" class Room { private: std::vector _days;公共:房间();房间(整数天,整数长度); 〜房间(); };
  • 请编辑您的问题以包含“room.h”的内容; cmets 中丢失了太多格式。
  • 你能展示一下你用过的包含防护吗?会导致此问题的一件事是,如果您不小心在“schedule.h”和“room.h”中为守卫使用了相同的宏名称。

标签: c++ cmake kdevelop


【解决方案1】:

即使你省略了一些重要的代码(即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

【讨论】:

  • 我不认为你可以有一个不完整类型的向量。此外,循环依赖如何产生 OP 实际得到的错误?如果像他所说的那样包含保护存在,那么 day.h 中的包含将失败,并且您会期望在 day.h 中出现错误。
  • @Mike:是的,您可以拥有一个不完整类型的向量,只要您不对其调用任何方法。试试看。当然,为了有用,你必须完成类型,但这可以在 cpp 文件而不是头文件中完成。
  • @Mike:循环依赖可能会产生错误,因为它取决于源文件中首先包含哪个标头。如果 schedule.cpp 首先包含 room.h,其中包含 day.h,其中包含 schedule.h,它尝试再次包含 room.h,那么重新包含将不会产生任何输出(因为现在定义了标头保护) ,所以当达到Schedule类的定义时,技术上已经包含了room.h,但是由于循环依赖,Room类还没有定义,导致OP报错。
  • @Adam:谢谢,您对向量的看法是正确的! (我确实尝试过,但我尝试实例化一个,但它不起作用:) 它确实作为成员工作,但正如你所说,大概需要在构造函数之前定义类以及你在向量上调用方法的任何地方)。
  • @Adam - 我不确定你在这种情况下的第二点,因为 schedule.hpp 包含在 schedule.cpp 的第 1 行中。
【解决方案2】:

这可能无关紧要,但我在您的标题中没有看到包含警卫。没关系,只是为了覆盖任何角度......

【讨论】:

  • 为简洁起见省略了它们。 (请参阅我的回答的第三条评论。)此外,在这种情况下,包含树几乎是一行,它们没有任何区别。
  • @Michael Dorgan:这是一个包含保护错误。详情见下文。谢谢!
【解决方案3】:

我无法从您的 schedule.h/.cpp 帖子中看出,但看起来您可能在 schedule.cpp 中有 #include "room.h",但您的 schedule.h 正在使用课堂房间。如果是这种情况,#include "room.h" 应该在 schedule.h 中。

或者您可以在 schedule.h 中使用前向声明。

【讨论】:

  • 包含行在 schedule.h 中
【解决方案4】:

理论上,g++ 应该在包含它的类之前编译一个类。

g++ 应该能够以它认为合适的任何顺序编译您的源文件。它包含标头到您的源代码中的顺序由您的#include 语句的顺序设置。

最可能的情况是类名是room,而不是Room。下一个可能是除了Room 之外的其他名称。不太可能是它位于根命名空间之外的命名空间中。

编辑:好的,如果不是这些,请确保包含的room.h 是您的room.h,而不是其他room.h。没有什么比编辑错误的文件副本更能浪费你的时间了。

编辑 2:我假设您的头文件具有通常的包含一次结构:

#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

【讨论】:

  • 我重新检查了一下,以防万一。房间拼写正确。没有命名空间定义,所以它使用 std。
  • @ravloony:它不使用 std 命名空间,它使用全局命名空间。
  • 为了简洁起见,我确实省略了它。我要将所有源代码复制到一个干净的文件夹中,然后重试。
  • @Mike DeSimone:将所有代码复制到干净的源文件夹会出现完全相同的错误。
  • @ravloony:这并不一定意味着它使用干净文件夹中的代码,如果有一个指令设置了文件夹外部的包含路径。
【解决方案5】:

Room.cpp 是什么样的?

另外..我从来没有遇到过任何问题,但也许你忘了在你的头文件底部多加一行?

【讨论】:

    猜你喜欢
    • 2019-04-28
    • 2015-12-29
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    相关资源
    最近更新 更多