【问题标题】:Cyclic Reference issue with includes for friend class包含朋友类的循环参考问题
【发布时间】:2021-11-12 12:43:34
【问题描述】:

我有 2 个类:S 和 R。R 有一个类型为 S 的实例。我想让 R 作为朋友类来访问 S 私有方法。 不幸的是,我无法构建它。请帮助我如何解决这个问题。我尝试了更多方式的前向声明,但没有奏效。我收到以下错误

R.hpp:12:15: error: ‘n1::n2’ has not been declared
  12 |         R(n1::n2::Sptr s);

提前非常感谢!

S.hpp:

#ifndef S_H
#define S_H
#include <memory>
    
namespace n1 {
  namespace n2  {
    class S  {   
      friend class c1::R;
      int x;
      inline void print();
    };
    
    using Sptr = std::shared_ptr<S>;
  }
}
    
#endif

S.cpp:

#include "S.hpp"
#include "R.hpp"
namespace n1 {
  namespace n2 {
    void S::print()
    {
      std::cout<<"S-print\n";
    }
  }
}

R.hpp:

#ifndef R_H 
#define R_H
#include <memory>
    
namespace n1  {
  namespace c1 {
    class S;
    struct R {
      R(n1::n2::Sptr s);
      void r();
      n1::n2::Sptr s_;
    };
  } 
}
#endif

R.cpp:

#include "R.hpp"
#include "S.hpp"

namespace n1 {
  namespace c1 {
    R::R(n1::n2::Sptr s):s_(s)
    {}

    void R::r() {
      s_->print();
    }
  }
}

main.cpp:

#include <iostream>
#include "R.hpp"
#include "S.hpp"
#include <memory>


int main() {
  auto s = std::make_shared<n1::n2::S>();
  auto r = std::make_shared<n1::c1::R>(s);
  r->r();
  //s.print();

  return 0;
}

 

【问题讨论】:

  • 不清楚什么是 c1::R。 c1 在哪里声明?
  • R 在 n1::c1 命名空间中。

标签: c++ c++14


【解决方案1】:

您可以通过在文件中使用以下修改来使程序工作(编译):

S.hpp

#ifndef S_H
#define S_H
#include <memory>
 namespace n1 
 {
     namespace c1 
     {
         class R;
     }
 }
namespace n1 {
  namespace n2  {
    class S  {   
      friend class c1::R;
      int x;
       void print();
    };
    
  //  using Sptr = std::shared_ptr<S>;
  }
}
    
#endif

S.cpp

#include "S.hpp"
//#include "R.hpp"
#include <iostream>
namespace n1 {
  namespace n2 {
    void S::print()
    {
      std::cout<<"S-print\n";
    }
  }
}

R.hpp

#ifndef R_H 
#define R_H
#include <memory>
 namespace n1 
 {
     namespace n2
     {
           class S;
           using Sptr = std::shared_ptr<S>;
     }
 }
namespace n1  {
  namespace c1 {
    class S;
    struct R {
      R(n1::n2::Sptr s);
      void r();
      n1::n2::Sptr s_;
    };
  } 
}
#endif

R.cpp

#include "R.hpp"
#include "S.hpp"

namespace n1 {
  namespace c1 {
    R::R(n1::n2::Sptr s):s_(s)
    {}

    void R::r() {
      s_->print();
    }
  }
}

以上程序的输出可见here

【讨论】:

  • 非常感谢您的帮助!
  • 不客气。
【解决方案2】:
  1. 删除所有交叉头文件包括。 (您似乎已经这样做了)
  2. 用标题中的前向声明替换缺少的符号。
  3. 将头文件包括已删除的内容添加到 cpp 文件中。 (您似乎已经这样做了)
  4. 在需要时重新定义 shared_ptr 别名。

【讨论】:

  • 请给出一个包含类和命名空间的可编译示例,我会接受你的回答。
  • @JohnKean 我不清楚我的说明中有什么不清楚。哪个步骤导致了问题?按顺序执行上述每个步骤后,您的代码将编译。您提供的代码是第一步(删除的交叉头文件包括),一些是第二步,而不是第三步。如果你的抱怨是“你没有为我做这些步骤”,那么恐怕我将不得不在没有接受复选标记的情况下生活。
  • 对于第 3 步添加头文件包括删除到 cpp 文件我已经在 cpp 文件中包含所有头文件,我在这里错过了什么?谢谢
  • @JohnKean 哎呀,抱歉 4。我数不过来。添加数字。
  • 感谢您的帮助!
猜你喜欢
  • 2020-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
  • 2021-08-16
  • 2019-08-29
相关资源
最近更新 更多