首页 > 解决方案 > 如何使用模板类头中的前向声明修复 C++ 循环依赖

问题描述

在我的面向应用的对象课程中,出于教学目的,我们被要求在不使用 STL 或 cstring 中的任何字符串操作函数的情况下开发一个功能齐全的 C++ 应用程序(稍后将涉及用于 GUI 的 SDL)。

在重新开发简单的字符串和列表容器层次类时,我遇到了一个循环依赖问题。以前,我使用前向声明解决了这些问题。然而,这一次,事情并没有按预期进行,这个问题让我忙了几个晚上。

这是我遇到的问题的简单UML图。

UML 图

每个类都有自己的.cpp.hpp文件,除了BaseListItemNotFoundExceptionusing在类声明上方BaseList声明。

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

即使这没有添加任何附加信息(恕我直言),让我准确地说BaseListHeplList类实际上是使用.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

标签: c++c++11templatescircular-dependencyforward-declaration

解决方案


  • 添加#include "BaseException.hpp"BaseList.hpp
  • 添加#include "HeplList.hpp"HeplString.cpp
  • 将前向声明添加template<class T> class HeplList;HeplString.hpp
  • 现在,您可能需要修改其他一些不包含BaseList.hpp标头的类,因为它们依赖标头HeplString.hpp为它们执行此操作。

推荐阅读