循环文件包含 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"(这是必需的,因为我使用了对象中的方法)