我相信我遇到了循环依赖问题。我研究了其他答案,但我不明白如何使用前向声明来解决我的问题。
我有以下构成:
+------------------+
|Session <---------------+
| | |
| +------------+ | Must know
| |Dataset | | about
| | | | ^
| | | | |
| | +---------+
| | | |
| | | |
| +------------+ |
| |
+------------------+
从下面发布的代码中,您能发现任何循环依赖关系或问题吗?如有必要,我可以发布更多代码。这是一个复杂的系统,我试图把问题归结为它最基本的部分。
Session.h
#include "Dataset.h"
...
namespace bmd2 {
class Session {
private:
std::vector<std::shared_ptr<bmd2::Dataset>>
datasetContainer; // error here
Dataset.h
#include "Session.h" // when I include this line I get strange errors
namespace bmd2 {
class Dataset {
private:
bmd::Session & session;
当我使数据集知道Session时,我得到的一些错误是:
Session.h Dataset in namespace bmd2 does not name a type
所以我尝试了这个:
Dataset.h
// removed include
namespace bmd2 {
class Dataset {
class Session;
private:
bmd2::Session & session;
Dataset.cpp
#include "Session.h"
bmd2::Dataset::Dataset(bmd2::Session & _session,
bmd2::Logger & _logger,
const std::string & filePath,
bmd2::File::FileMode fileMode)
: session(_session), logger(_logger)
{
我仍然得到:命名空间bmd2中的'Session'没有命名类型。这太令人沮丧了。
答案 0 :(得分:1)
实际上,你不能同时拥有两个标题。幸运的是,Dataset
不需要Session
的完整定义来声明对一个的引用;只是声明类(在其命名空间内):
class Session;
确保它在命名空间中;您的更新表明您已将其放在Dataset
内,它在不同的范围内声明了另一个类。
答案 1 :(得分:1)
您的数据集仅包含对Session
的引用,因此您不需要Session
类的定义,只需在标题中声明它就足够了:
<强> Dataset.h 强>
namespace bmd2 {
class Session; //class declaration
class Dataset {
private:
bmd::Session & session;
并且include移动到cpp文件,因此您的类也可以在实现中使用它的方法:
<强> Dataset.cpp 强>
#include "Session.h"
...
这称为前向声明。请参阅this question的详细信息。
答案 2 :(得分:0)
由于您只持有引用(指针也可以),而不是实际实例,如果您仔细按照这些步骤操作,您将构建并链接正常:
#pragma once
或在所有.h文件的顶部加入警卫fwd.hpp
文件Session.hpp
和Data.hpp
没有调用彼此功能的实现细节。如果你这样做,把它们放在你的.cpp文件中,并在那里使用适当的cross-hpp。Session.hpp
和Data.hpp
中,仅包含fwd.hpp
- 不要包含彼此的标题。如果您的两个类包含彼此的引用或指针,则此过程也将很有用。只要在.cpp文件中保留交叉函数调用(如果必须从标题中调用,则可以对模板类进行调整)。