Циркулярное включение файла C ++ - PullRequest
2 голосов
/ 01 апреля 2020

Скажите, что у нас есть два класса:

// 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();
}

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

Добавление #include в оба файла приведет к этой ошибке:

Handler.hpp: error: ‘Object’ has not been declared
         update(Object*);
                ^

Если я добавить предварительное объявление объекта в обработчик, я получаю это:

Object.hpp: error: ‘Handler’ does not name a type
         Handler handler

Включение объекта в Handler.hpp и прямое объявление обработчика в Object.hpp дает это:

Object.hpp: error: field ‘h’ has incomplete type ‘Handler’
         Handler handler;
                 ^

Между тем, включая обработчик в Object.hpp прямое объявление объекта в Handler.hpp дает следующее:

Handler.cpp: error: invalid use of incomplete type ‘class Object’
     o->method();
      ^

Кажется, я не могу понять, как включить файлы друг в друга. Эта структура основана на шаблоне развязки компонентов из паттернов программирования игр Роберта Нистрома . Любая помощь приветствуется. Спасибо

Ответы [ 2 ]

2 голосов
/ 01 апреля 2020

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

Проблема с

Object.hpp: error: ‘Handler’ does not name a type
         Handler handler  //<-- Declaration of object of type Handler, not pointer

заключается в том, что handler был объявлен как объект, а не указатель. Таким образом, компилятор должен знать определение. Вот почему предварительной декларации недостаточно. Если вы добавите предварительное объявление Handler в Object.hpp, который вы дали, оно должно работать:

// 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();
}

Отредактировано, чтобы добавить include в Object. cpp и удалить первый абзац согласно комментарию @ TonyK

1 голос
/ 01 апреля 2020

Нашел проблему. Спасибо всем, что нашли время, чтобы попытаться помочь мне, и особенно спасибо @Yksisarvinen за полезную ссылку.

Проблема в том, что я поместил #include в файл .hpp, и это создает проблема для компилятора, несмотря на то, что я включил защиту.

Я решил это, используя только предварительные объявления в файлах .hpp, которым не нужен код из включенных классов, а затем добавил #include в . cpp файлов (где я использую методы из включенного класса).

В основном я сделал следующее:

  • Я добавил #include " Handler.hpp "в Object.hpp (класс Object содержит объект Handler, который вызывает конструктор, который требует #include)
  • Я добавил только предварительное объявление Object в Handler.hpp (Handler.hpp не нам не нужен код из файлов объектов, нужно просто знать, что класс объекта существует)
  • И, наконец, я добавил #include "Object.hpp" в обработчик. cpp (N необходимо, потому что я использую метод из Object)
...