如何将A实现为B,将B实现为A(不创建循环)?

时间:2019-06-12 15:42:40

标签: c++

我正在学习C ++,我正在尝试创建一个“在线商店”,您可以在其中发布文章并对此发表评论,评论属于文章,并且文章可以包含很多评论,但是我现在不知道如何对其进行编码而不创建循环

我尝试使用Article.h-> #include“ Comment.h”,反之亦然,但是当我尝试编译它时,会创建一个循环,其中A导入B,B导入A

评论.h

#include <string>

//This is what I've tried but it creates a loop
#include "Article.h"


using namespace std;
//Class
class Comment
{
    private:
        Article article;
        string description;
        string rating;
};

Article.h


#include <string>
#include <map>

//The other part of my buggy-loop
#include "Comentario.h"

class Article
{
    private:
        map<string, int> art_comments;
        string name;
        string rating;
};

更新

谢谢大家,您给我的Resolve build errors due to circular dependency amongst classes解决了我的问题

这个问题已经解决了,我该删除这个帖子吗?

2 个答案:

答案 0 :(得分:2)

您需要退后一步。

您首先需要分析您想做什么,然后再想想如何做。然后,您将执行此操作(编写代码),然后对其进行测试。实际上,还有更多步骤。

所以让我们从WHAT开始。您有一些具有关系的实体。所以你有

  • “在线商店”
  • “文章”和
  • 对“文章”的“评论”

那是您的实体或对象。这些实体有关系

  • 在线商店有0或1或许多文章
  • 现有文章可以有0个或1个或很多评论

因此,您要存储0或1或许多“东西”。为了存储这样的“东西”,C ++在STL中提供了容器。例如std :: vector或std :: list。您需要阅读这些容器的属性,并为您选择最合适的容器。在这种情况下,肯定是std :: vector。它可以包含0个或多个元素,并且可以动态增长。

对于C ++和面向对象语言中的关系,通常使用所谓的“具有”或“是”属性。通过推导对“是”关系进行建模,通过“包含”来对“具有”类型进行建模。

示例:

#include <string>
#include <vector>

// "Is a"-relation. Done by deriving from base class Shape
struct Shape
{
  std::string name;
};
// A line is a shape
struct Line : public Shape
{
  int length;
};

// "Has a"-relation. Done by containment. Class online Shop contains articles
struct Article
{
  std::string articleName;
};
struct OnlineShop
{
  std::string shopName;
  std::vector<Article> article;
};


int main()
{
  Line line{ "long line",12345 };

  std::string myShopName{ "My Shop" };
  std::vector<Article> myArticles{ Article{ "Apple"}, Article{"Banana"} };
  OnlineShop myOnlineShop{ myShopName, myArticles };

  return 0;
}

现在您可能会了解一些。

因此,对于您的解决方案,在考虑了实体和关系之后,您可能会得出一个可能的解决方案:

  • 您将创建一个类OnlineStore
  • 您将创建一个类Article
  • 还有一个班级评论

由于可能有很多文章和评论,您将把它们放在std :: vector中。然后,“在线商店”类将继续包含“评论”类的“商品”类。

因此,将没有循环依赖性。在大多数情况下,循环引用是设计缺陷的指标。

下面显示了这种实现的框架:

#include <string>
#include <vector>

struct Comment 
{
   std::string commentText{};
   std::string commentAuthor{};
};
struct Article
{
   std::string articleName{};
   std::vector<Comment> comment{};
};
struct OnlineShop
{
   std::vector<Article> article{};
};

int main()
{
   OnlineShop onlineShop{};
   return 0;
}

请根据这种方法定义您的课程。然后添加所需的功能。

还请阅读有关面向对象编程的原理。

希望这会有所帮助。 。

答案 1 :(得分:2)

这是一个很好的问题!尽管对我来说,没有太多理由让Comment了解有关Article的知识,但尤其是因为Article可能会使用std拥有其所有Comments,因此,使用对文章的引用以及正向声明可能是您要尝试做的事情。 :: vector <评论>。

现在,您的comentario.h文件如下所示:

// comentario.h
class Comment {
public:
  ...
private:
  Article article;
  [other implementation details for an Article]
}

由于您的评论绝对不应该拥有文章,因此我们可以这样重写comentario.h:

// comentario.h
class Article; // this is a forward declaration in order to reference an Article

class Comment {
public:
  Comment(Article& article) // a Comment constructor--requires an Article
  ... // other Comment implementation details
private:
  Article& article;  // reference an existing Article
  ...
  // no need for Article implementation details at all in Comment
}

// comentario.cpp
#include "include/comentario.h"

#include "include/article.h" // we can include article.h now since we're outside the header

Comment::Comment(Article& article)  // the Comment constructor
: article(article) { // initialize the reference to an Article

}

这是执行此操作的一种方法。我不会亲自给Comment提供任何有关Article的知识,但是如果需要的话,我会为Article详细信息(例如标题)创建一个只读包装,然后在Comment中引用它。

旁注:许多程序员不鼓励在标头中使用“使用名称空间xx”。