循环文件包含 C++
Circular file inclusion C++
假设我们有两个 类:
// Object.hpp
class Object
{
Handler* h;
Object();
void method();
};
// Object.cpp
Object::Object()
{
h = new Handler();
}
// Handler.hpp
class Handler
{
void update(Object*);
};
// Handler.cpp
void Handler::update(Object* o)
{
o->method();
}
如何link四个文件不出现包含错误?我已经尝试了所有我能想到的和我能在网上找到的方法。
在两个文件中添加 #include
将导致此错误:
Handler.hpp: error: ‘Object’ has not been declared
update(Object*);
^
如果我在 Handler 中添加对象的前向声明,我会得到:
Object.hpp: error: ‘Handler’ does not name a type
Handler handler
在 Handler.hpp 中包含 Object 并在 Object.hpp 中转发声明 Handler 给出:
Object.hpp: error: field ‘h’ has incomplete type ‘Handler’
Handler handler;
^
与此同时,在 Object.hpp 中包含 Handler,在 Handler.hpp 中向前声明对象会给出:
Handler.cpp: error: invalid use of incomplete type ‘class Object’
o->method();
^
我似乎想不出将文件相互包含的方法。该结构基于 Robert Nystrom's Game Programming Patterns 中的解耦组件模式。任何帮助表示赞赏。谢谢
您发布的错误似乎不是来自您提供的代码。
的问题
Object.hpp: error: ‘Handler’ does not name a type
Handler handler //<-- Declaration of object of type Handler, not pointer
是handler
被声明为一个对象,而不是一个指针。因此,编译器需要知道定义。这就是为什么前瞻性声明是不够的。如果您在给定的 Object.hpp 中添加 Handler 的前向声明,它应该可以工作:
// Object.hpp
//forward-declaration of Handler
class Handler;
class Object
{
Handler* h;
Object();
void method();
};
// Object.cpp
//include Handler.hpp
#include "Handler.hpp"
Object::Object()
{
h = new Handler();
}
// Handler.hpp
//include Object.hpp
#include "Object.hpp"
class Handler
{
void update(Object*);
};
// Handler.cpp
void Handler::update(Object* o)
{
o->method();
}
根据@TonyK 的评论
进行编辑以在 Object.cpp 中添加并删除第一段
找到问题了。感谢大家花时间尝试帮助我,特别感谢@Yksisarvinen 提供的帮助 link.
问题是我在 .hpp 文件中放置了#includes,这对编译器造成了问题,即使我已经包含了保护。
我通过仅在 .hpp 文件中使用前向声明解决了这个问题,这些声明不需要包含的 classes 中的任何代码,然后将 #include 添加到 .cpp 中 个文件(我在其中使用了包含的 class 中的方法)。
基本上我做了以下事情:
- 我在Object.hpp中添加了一个#include "Handler.hpp"(对象class包含一个Handler对象,它调用需要#include的构造函数)
- 我只在 Handler.hpp 中添加了一个对象的前向声明(Handler.hpp 不需要对象文件中的任何代码,它只需要知道一个对象 class 存在)
- 然后最后我在Handler.cpp中添加了#include "Object.hpp"(这是必需的,因为我使用了对象中的方法)
假设我们有两个 类:
// Object.hpp
class Object
{
Handler* h;
Object();
void method();
};
// Object.cpp
Object::Object()
{
h = new Handler();
}
// Handler.hpp
class Handler
{
void update(Object*);
};
// Handler.cpp
void Handler::update(Object* o)
{
o->method();
}
如何link四个文件不出现包含错误?我已经尝试了所有我能想到的和我能在网上找到的方法。
在两个文件中添加 #include
将导致此错误:
Handler.hpp: error: ‘Object’ has not been declared
update(Object*);
^
如果我在 Handler 中添加对象的前向声明,我会得到:
Object.hpp: error: ‘Handler’ does not name a type
Handler handler
在 Handler.hpp 中包含 Object 并在 Object.hpp 中转发声明 Handler 给出:
Object.hpp: error: field ‘h’ has incomplete type ‘Handler’
Handler handler;
^
与此同时,在 Object.hpp 中包含 Handler,在 Handler.hpp 中向前声明对象会给出:
Handler.cpp: error: invalid use of incomplete type ‘class Object’
o->method();
^
我似乎想不出将文件相互包含的方法。该结构基于 Robert Nystrom's Game Programming Patterns 中的解耦组件模式。任何帮助表示赞赏。谢谢
您发布的错误似乎不是来自您提供的代码。
的问题Object.hpp: error: ‘Handler’ does not name a type
Handler handler //<-- Declaration of object of type Handler, not pointer
是handler
被声明为一个对象,而不是一个指针。因此,编译器需要知道定义。这就是为什么前瞻性声明是不够的。如果您在给定的 Object.hpp 中添加 Handler 的前向声明,它应该可以工作:
// Object.hpp
//forward-declaration of Handler
class Handler;
class Object
{
Handler* h;
Object();
void method();
};
// Object.cpp
//include Handler.hpp
#include "Handler.hpp"
Object::Object()
{
h = new Handler();
}
// Handler.hpp
//include Object.hpp
#include "Object.hpp"
class Handler
{
void update(Object*);
};
// Handler.cpp
void Handler::update(Object* o)
{
o->method();
}
根据@TonyK 的评论
进行编辑以在 Object.cpp 中添加并删除第一段找到问题了。感谢大家花时间尝试帮助我,特别感谢@Yksisarvinen 提供的帮助 link.
问题是我在 .hpp 文件中放置了#includes,这对编译器造成了问题,即使我已经包含了保护。
我通过仅在 .hpp 文件中使用前向声明解决了这个问题,这些声明不需要包含的 classes 中的任何代码,然后将 #include 添加到 .cpp 中 个文件(我在其中使用了包含的 class 中的方法)。
基本上我做了以下事情:
- 我在Object.hpp中添加了一个#include "Handler.hpp"(对象class包含一个Handler对象,它调用需要#include的构造函数)
- 我只在 Handler.hpp 中添加了一个对象的前向声明(Handler.hpp 不需要对象文件中的任何代码,它只需要知道一个对象 class 存在)
- 然后最后我在Handler.cpp中添加了#include "Object.hpp"(这是必需的,因为我使用了对象中的方法)