c++ - 如何使用模板类头中的前向声明修复 C++ 循环依赖
问题描述
在我的面向应用的对象课程中,出于教学目的,我们被要求在不使用 STL 或 cstring 中的任何字符串操作函数的情况下开发一个功能齐全的 C++ 应用程序(稍后将涉及用于 GUI 的 SDL)。
在重新开发简单的字符串和列表容器层次类时,我遇到了一个循环依赖问题。以前,我使用前向声明解决了这些问题。然而,这一次,事情并没有按预期进行,这个问题让我忙了几个晚上。
这是我遇到的问题的简单UML图。
每个类都有自己的.cpp
和.hpp
文件,除了BaseListItemNotFoundException
我using
在类声明上方BaseList
声明。
class BaseListItemNotFoundException: BaseException {
using BaseException::BaseException;
};
即使这没有添加任何附加信息(恕我直言),让我准确地说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
解决方案
- 添加
#include "BaseException.hpp"
到BaseList.hpp
- 添加
#include "HeplList.hpp"
到HeplString.cpp
- 将前向声明添加
template<class T> class HeplList;
到HeplString.hpp
- 现在,您可能需要修改其他一些不包含
BaseList.hpp
标头的类,因为它们依赖标头HeplString.hpp
为它们执行此操作。
推荐阅读
- javascript - Javascript减少速记不返回对象
- javascript - 计算一个字符串中有多少个特定字符
- gitlab - 即使存储库存在于 git_data_dirs 路径中,Gitlab 也会返回“No Repository”
- javascript - 避免在 es6 中导出单例
- spring-boot - 使用 Jenkins 管道,使用 nohup 在后台运行 jar 文件不会启动 jar
- php - 使用 PHP 的多个单选按钮值
- bash - 在 UNIX 中动态创建和分配变量
- javascript - React 路由器无法正确渲染起始页面组件
- python - Python,请求,BS4:提交一个没有名字的按钮
- c# - 队列关闭时,RabbitMQ 事务正在无异常地提交