C++ 中的拷贝控制

发布于 2024-12-23 22:18:14 字数 5078 浏览 1 评论 0

一般来说进行资源管理的类都需要对拷贝过程进行控制,另外在类需要进行某些记录操作时 也需要进行拷贝控制。以博客生成为例,一篇博客可能具有多个标签,而一个标签下面也会 管理多篇博客。

0.1 Tag 类的实现

  #include <set>
  #include <string>
  #include <iostream>

  class Blog;

  class Tag {
    friend class Blog;
    friend std::ostream& operator<<(std::ostream& os, Tag const& tag);
  public:
    Tag(std::string const& __name = "") : name(__name) { }
    void add(Blog*);
    void remove(Blog*);
    std::string const& get_name() { return name; }
  private:
    std::string name;       // 标签的名字
    std::set<Blog*> blogs;  // 属于此标签的 Blog
  };

  void Tag::add(Blog* blog)
  {
    blogs.insert(blog);
  }

  void Tag::remove(Blog* blog)
  {
    blogs.erase(blog);
  }

0.2 Blog 类的实现

  #include <iostream>
  #include <string>
  #include <set>

  class Tag;

  class Blog {
    friend class Tag;
    friend std::ostream& operator<<(std::ostream& os, Blog const& blog);
  public:
    Blog(std::string const& __content = "") : content(__content) { }
    // 拷贝控制成员函数
    Blog(Blog const&);             // 拷贝构造
    Blog& operator=(Blog const&);  // 拷贝赋值
    ~Blog();                       // 析构
    // 从给定的 Tag 中添加或删除本 Blog
    void add_to(Tag&);
    void remove_from(Tag&);
    std::string const& get_content() { return content; }
  private:
    std::string content;           // Blog 的内容
    std::set<Tag*> tags;           // 本 Blog 的 tags,被隐式初始化为空集合
    void add_to_tags(Blog const&); // 将本 Blog 添加到参数 Blog 的所有 Tag 中
    void remove_from_tags();       // 从 tags 中的每个 Tag 中删除本 Blog
  };

  void Blog::add_to(Tag& tag)
  {
    tags.insert(&tag);
    tag.add(this);
  }

  void Blog::remove_from(Tag& tag)
  {
    tags.erase(&tag);
    tag.remove(this);
  }

  void Blog::add_to_tags(Blog const& blog)
  {
    for (auto tag : blog.tags)
      tag->add(this);
  }

  void Blog::remove_from_tags()
  {
    for (auto tag : tags)
      tag->remove(this);
  }

  Blog::Blog(Blog const& blog) : content(blog.content), tags(blog.tags)
  {
    add_to_tags(blog);
  }

  Blog::~Blog()
  {
    remove_from_tags();
  }

  Blog& Blog::operator=(Blog const& blog)
  {
    // 先将本 Blog 从原来的 tags 中删除,再加入到 blog 参数的 tags 列表中,从而处
    // 理自赋值情况
    remove_from_tags();
    content = blog.content;
    tags = blog.tags;
    add_to_tags(blog);
    return *this;
  }

0.3 测试我们的 BlogTag

  #include <fmt/core.h>

  <<Tag-class>>
  <<Blog-class>>

  std::ostream& operator<<(std::ostream& os, Tag const& tag)
  {
    os << fmt::format("Tag({0}) has {1} blogs:\n", tag.name, tag.blogs.size());
    std::set<Blog*>::size_type index = 0;
    std::set<Blog*>::const_iterator iter = tag.blogs.cbegin();
    for (; index < tag.blogs.size(); ++index, ++iter) {
      os << fmt::format("[{0}] ", index + 1) << (*iter)->get_content() << std::endl;
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, Blog const& blog)
  {
    os << fmt::format("Blog({0}) has {1} tags: ", blog.content, blog.tags.size());
    std::set<Tag*>::size_type index = 0;
    std::set<Tag*>::const_iterator iter = blog.tags.cbegin();
    for (; index < blog.tags.size() - 1; ++index, ++iter)
      os << (*iter)->get_name() << ", ";
    return os << (*iter)->get_name() << "." << std::endl;
  }

  int main()
  {
    Tag python("Python"), cpp("C++"), program("Program languages");

    Blog b1("Python is elegant.");
    Blog b2("Python is simple.");
    Blog b3("C++ is evil.");
    b1.add_to(python);
    b2.add_to(python);
    b3.add_to(cpp);
    b1.add_to(program);
    b2.add_to(program);
    b3.add_to(program);

    std::cout << python << std::endl;
    std::cout << cpp << std::endl;
    std::cout << program << std::endl;

    // 从 b3 拷贝构造 b4
    Blog b4(b3);
    std::cout << cpp << std::endl;
    std::cout << b4 << std::endl;

    b4 = b1;
    std::cout << cpp << std::endl;
    std::cout << python << std::endl;
    std::cout << b4 << std::endl;
  }
Tag(Python) has 2 blogs:
[1] Python is elegant.
[2] Python is simple.

Tag(C++) has 1 blogs:
[1] C++ is evil.

Tag(Program languages) has 3 blogs:
[1] Python is elegant.
[2] Python is simple.
[3] C++ is evil.

Tag(C++) has 2 blogs:
[1] C++ is evil.
[2] C++ is evil.

Blog(C++ is evil.) has 2 tags: C++, Program languages.

Tag(C++) has 1 blogs:
[1] C++ is evil.

Tag(Python) has 3 blogs:
[1] Python is elegant.
[2] Python is simple.
[3] Python is elegant.

Blog(Python is elegant.) has 2 tags: Python, Program languages.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

上一篇:

下一篇:

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

温柔戏命师

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

亚希

文章 0 评论 0

cyp

文章 0 评论 0

北漠

文章 0 评论 0

11223456

文章 0 评论 0

坠似风落

文章 0 评论 0

游魂

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文