这是循环依赖吗?我该如何解决?

时间:2014-02-24 06:19:41

标签: c++

我相信我遇到了循环依赖问题。我研究了其他答案,但我不明白如何使用前向声明来解决我的问题。

我有以下构成:

+------------------+
|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'没有命名类型。这太令人沮丧了。

3 个答案:

答案 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)

由于您只持有引用(指针也可以),而不是实际实例,如果您仔细按照这些步骤操作,您将构建并链接正常:

  1. 确保您拥有#pragma once或在所有.h文件的顶部加入警卫
  2. 创建一个具有Session和DataSet前向声明的fwd.hpp文件
  3. 确保您的Session.hppData.hpp没有调用彼此功能的实现细节。如果你这样做,把它们放在你的.cpp文件中,并在那里使用适当的cross-hpp。
  4. Session.hppData.hpp中,仅包含fwd.hpp - 不要包含彼此的标题。
  5. 如果您的两个类包含彼此的引用或指针,则此过程也将很有用。只要在.cpp文件中保留交叉函数调用(如果必须从标题中调用,则可以对模板类进行调整)。