Как исправить циклическую зависимость C ++ с помощью предварительного объявления в заголовке класса шаблона - PullRequest
0 голосов
/ 05 декабря 2018

В целях обучения на моих курсах по прикладным ориентированным объектам нас просят разработать полнофункциональное приложение C ++ без использования STL или каких-либо функций манипуляции со строками из cstring (SDL для GUI будет задействован на более позднем этапе).

Перерабатывая простые классы String и иерархии контейнеров списков, я столкнулся с проблемой циклической зависимости.Ранее я исправлял подобные проблемы, используя предварительную декларацию.Однако на этот раз все идет не так, как ожидалось, и эта проблема несколько дней занимала меня.

Вот простая UML-диаграмма проблемы, с которой я столкнулся.

UML diagram

Каждый класс имеет свои собственные файлы .cpp и .hpp, за исключением BaseListItemNotFoundException, который я объявляю с помощью оператора using над объявлением класса BaseList.

class BaseListItemNotFoundException: BaseException {
    using BaseException::BaseException;
};

Даже если это не добавляет каких-либо добавленных фрагментов информации (IMHO), позвольте мне точно указать, BaseList и HeplList классы на самом деле являются шаблонными классами, определенными с использованием .ipp и .hpp.

Я опустил некоторые другие классы, задействованные для ограничения среды минимальным рабочим примером (иерархия универсальных классов итераторов и Cell используется в качестве полезной нагрузки для списков).Защита заголовка с использованием условий define и ifndef была удалена для ясности.

Вот отрывок файлов:

BaseList.hpp:

#include <cstddef>
#include <iostream>
#include "Cell.hpp"

class HeplString; // Forward declaration

#include "BaseException.hpp"
class BaseListItemNotFoundException: BaseException {
    using BaseException::BaseException;
};

template<class T>
class BaseList {
    // code
};

HeplList.hpp:

#include <cstddef>
#include "BaseList.hpp"
#include "Cell.hpp"

template<class T>
class HeplList : public BaseList<T> {
    // code
};

#include "HeplList.ipp"

HeplString.hpp:

#include <cstddef>
#include <iostream>
#include <ostream>
#include <fstream>
#include "HeplList.hpp"

class HeplString {
    // code
};

BaseException.hpp:

#include "HeplString.hpp"
#include "BaseList.hpp"

class BaseException {
    // code
};

Основная проблема, с которой я сталкиваюсь в этом примере, - это ошибки типавот этот:

src/tests/../BaseException.hpp:9:20: error: field ‘msg’ has incomplete type ‘HeplString’
         HeplString msg;
                    ^~~
In file included from src/tests/../HeplList.hpp:5,
                 from src/tests/../HeplString.hpp:9,
                 from src/tests/test.cpp:2:
src/tests/../BaseList.hpp:9:7: note: forward declaration of ‘class HeplString’
 class HeplString;
       ^~~~~~~~~~

Я не понимаю, что я делаю здесь неправильно.Чтение других подобных проблем не помогло.

Мой git-репозиторий с полным кодом доступен здесь, если необходимо: https://github.com/wget/hepl-2-cpp

1 Ответ

0 голосов
/ 18 декабря 2018
  • Добавить #include "BaseException.hpp" к BaseList.hpp
  • Добавить #include "HeplList.hpp" к HeplString.cpp
  • Добавить предварительную декларацию template<class T> class HeplList; к HeplString.hpp
  • Теперь вам может понадобиться изменить некоторые другие ваши классы, которые не включали заголовок BaseList.hpp, потому что они полагались на заголовок HeplString.hpp, чтобы сделать это для них.
...