【发布时间】:2018-12-05 19:41:40
【问题描述】:
在我的面向应用的对象课程中,出于教学目的,我们被要求在不使用 STL 或 cstring 中的任何字符串操作函数的情况下开发一个功能齐全的 C++ 应用程序(稍后将涉及用于 GUI 的 SDL)。
在重新开发简单的字符串和列表容器层次类时,我遇到了循环依赖问题。以前,我使用前向声明解决了这些问题。然而,这一次,事情并没有按预期进行,这个问题让我忙了几个晚上。
这是我遇到的问题的简单 UML 图。
每个类都有自己的.cpp 和.hpp 文件,除了BaseListItemNotFoundException 我在BaseList 类声明上方使用using 声明。
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
【问题讨论】:
-
为什么
BaseException需要了解BaseList和HeplString? -
BaseException在内部使用HeplString来存储自定义错误消息。因此,BaseException通过使用HeplString隐式使用BaseList。 -
你似乎在这里绕了一圈。戒指必须在某处被打破。您永远不能仅使用前向声明创建数据成员,但您可以创建指向它的指针或引用。这意味着实例将不得不生活在其他地方。
-
@ravnsgaard 在提议的解决方案中我也看到了使用引用,但是对于当前的用例,我不知道如何以优雅的 OOP 方式实现它:-/
-
您需要将声明和定义明确分开。
HeplString声明只需要HeplList的前向声明; 定义需要HeplList的完整定义。
标签: c++ c++11 templates circular-dependency forward-declaration