C++primer 练习13.36

#pragma once
#include<string>
#include<set>
using namespace std;

class Message
{
    friend class Folder;
    friend void swap(Message &lhs, Message &rhs);
public:
    explicit Message(const string &str=""):contents(str){}
    Message(const Message&);
    Message& operator=(const Message);//采用非引用类型,实现自赋值情况出现时,也能成功,但多了一次拷贝构造
    ~Message();
    void save(Folder &);
    void remove(Folder &);
private:
    string contents;
    set<Folder*> folders;
    void add_to_Folders(const Message&);
    void remove_from_Folders();
};

class Folder
{
public:
    Folder(const Folder&);//拷贝构造函数
    Folder& operator=(const Folder);//拷贝赋值运算符,采用非引用类型,实现出现自赋值情况时,也能成功,但多了一次拷贝构造
    ~Folder();                //析构函数
    void addMsg(Message *);   //添加message
    void remMsg(Message *);   //去除message
private:
    set<Message*> Mes;
    void addAllMsg();        //拷贝构造函数和拷贝赋值预算符的辅助函数
    void removeAllMsg();     //拷贝赋值运算符和析构函数的辅助函数
};

void Folder::addMsg(Message *m)
{
    if(Mes.find(m)==Mes.end())//防止在调用m->save(*this)时的从复插入(虽然重复插入对于set来说没什么关系)
        Mes.insert(m);
    if (m->folders.find(this) == m->folders.end())//给递归调用一个结束条件,防止无限调用
        m->save(*this);
}

void Folder::remMsg(Message *m)
{
    if (Mes.find(m) != Mes.end())//防止在调用m->remove(*this)时的从复删除(虽然重复删除对于set来说没什么关系)
        Mes.erase(m);
    if (m->folders.find(this) != m->folders.end())//给递归调用一个结束条件,防止无限调用
        m->remove(*this);
}

void Folder::addAllMsg()        //拷贝构造函数和拷贝赋值预算符的辅助函数
{
    for (auto &m : Mes)         //对Mes集合中的每一个指针对象都调用save()函数
        m->save(*this);
}

Folder::Folder(const Folder &f)
{
    Mes = f.Mes;              //将f中数据成员拷贝过来
    addAllMsg();              //调用addALLMsg将这个Folder添加到所有对应的message中去
}

void Folder::removeAllMsg()   //拷贝赋值运算符和析构函数的辅助函数
{
    for (auto &m : Mes)       //对Mes集合中的每一个指针对象都调用remover()函数
        m->remove(*this);
}

Folder& Folder::operator=(const Folder f)//采用非引用类型是为了保护出现自赋值的情况时,也能正常运行
{
    removeAllMsg();          //将数据成员中所包含的所有message都调用remove()函数,实现删除这个文件夹的作用
    Mes = f.Mes;             //将新的数据成员拷贝过来
    addAllMsg();             //将数据成员中所包含的所有message都调用remover()函数,完成为这个文件夹赋值右侧文件夹的步骤
    return *this;
}

Folder::~Folder()
{
    removeAllMsg();         //将数据成员中所包含的所有message都调用remove()函数,实现删除这个文件夹的作用
}

void Message::save(Folder &f)
{
    folders.insert(&f);
    f.addMsg(this);
}

void Message::remove(Folder &f)
{
    folders.erase(&f);
    f.remMsg(this);
}

void Message::add_to_Folders(const Message &m)
{
    for (auto &f : m.folders)
        f->addMsg(this);
}

Message::Message(const Message &m) :contents(m.contents), folders(m.folders)
{
    add_to_Folders(m);
}

void Message::remove_from_Folders()
{
    for (auto f : folders)
        f->remMsg(this);
}

Message::~Message()
{
    remove_from_Folders();
}

Message& Message::operator=(const Message rhs)
{
    remove_from_Folders();
    contents = rhs.contents;
    folders = rhs.folders;
    add_to_Folders(rhs);
    return *this;
}

void swap(Message &lhs, Message &rhs)
{
    set<Folder*> lfolders = lhs.folders;
    set<Folder*> rfolders = rhs.folders;
    for (auto f : rhs.folders)
        f->remMsg(&rhs);
    for (auto f : lhs.folders)
        f->remMsg(&rhs);
    lhs.folders = rhs.folders;
    rhs.folders = lhs.folders;
    swap(lhs.contents, rhs.contents);
    for (auto f : lhs.folders)
        f->addMsg(&lhs);
    for (auto f : rhs.folders)
        f->addMsg(&rhs);
}
时间: 2024-08-29 08:07:00

C++primer 练习13.36的相关文章

【C++ Primer 第13章】2. 拷贝控制和资源管理

拷贝控制和资源管理 • 类的行为像一个值.意味着它应该有自己的状态,当我们拷贝一个像值得对象时,副本和原对象是完全独立的,改变副本不会对原对象有任何影响. • 行为像指针的类则共享状态.当我们拷贝一个这种类的对象时,副本和原对象使用相同的底层数据,改变副本也会改变原对象. 13.2节练习 1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 class HasPtr { 6 public: 7 HasP

C++ Primer Plus 13章的疑问

1 void show(const Brass &rba) 2 { 3 rba.ViewAcct(); 4 cout<<endl; 5 } 6 7 void inadequate(Brass ba) 8 { 9 ba.ViewAcct(); 10 cout<<endl; 11 } 12 13 14 BrassPlus buzz("Buzz Parsec", 00001111, 4300); 15 16 show(buzz); 17 inadequate(

C++primer 练习13.39

13.39 编写你自己版本的StrVec,包括自己版本的reserve,capacity(参见9.4节,第318页)和resize(参见9.3.5节,第314页) 13.40 为你的StrVec类添加一个构造函数,它接受一个initializer_list<string>参数 这是StrVec.h #pragma once #include<string> #include<memory> #include<initializer_list> using n

函数指针(——C primer 第13章)

函数指针: int  f(int);//声明一个函数 int  (*pf)(int)=&f;//创建一个函数指针,并将函数f的函数地址对它进行初始化. 其实函数名在被使用时,总是由编译器将它转化为指针.上面的那个&那个并非必要,只是显示 的说明编译器将隐式执行的任务. int ans; ans=f(25);//使用名字调用函数f,其实在执行时,函数名f被转化为函数指针,指向函数在内存中的地址. ans=(*pf)(25);//将函数指针转化为函数名,其实在执行时又转化回去了 ans=pf(

高级声明(——C primer第13章)

高级声明: (1) int *f,g: 这个只声明了一个f指针.*是都是紧跟在其后的. (2) int *f(); f是一个函数,它的返回值是一个指向整型的指针. (3) int  (*f)(); f是一个函数指针,这个函数的返回值是一个int类型. (4) int *(*f)(); f是一个函数指针,这个函数的返回值是一个int*类型 (5) int f[]; f是一个整型数组,数组的长度暂时省略 (6) int *f[] f是一个数组,数组的元素是指向整型的指针 (7)  int f()[]

c++primer第五版第十九章练习

19.1 #include <iostream> #include <cstdlib> void *operator new(std::size_t n){ std::cout << "new(size_t)\n"; if (void *mem = malloc(n)) return mem; else throw std::bad_alloc(); } void operator delete(void *mem) noexcept{ std::c

第 13 章

13.1 [出题思路] 理解拷贝构造函数的基本概念. [解答] 如果构造函数的第一个参数是自身类类型的引用,且所有其他参数(如果有的话)都有默认值,则此构造函数是拷贝构造函数.拷贝构造函数在以下几种情况下会被使用: 拷贝初始化(用 = 定义变量). 将一个对象作为实参传递给非引用类型的形参. 一个返回类型为非引用类型的函数返回一个对象. 用花括号列表初始化一个数组中的元素或一个聚合类中的成员. 初始化标准库容器或调用其 insert/push 操作时,容器会对其元素进行拷贝初始化. 13.2 [

《C++primer(第五版)》学习之路-第十三章:拷贝控制

[ 声明:版权所有,转载请标明出处,请勿用于商业用途.  联系信箱:[email protected]] 13.1 拷贝.赋值与销毁 1.当定义一个类时,我们显式地或隐式地指定在此类型的对象拷贝.移动.赋值和销毁时做什么.一个类通过定义五种特殊的成员函数来控制这些操作,包括:拷贝构造函数,拷贝赋值运算符,移动构造函数,移动赋值运算符和析构函数. 2.在一个构造函数中,成员的初始化是在函数体执行之前完成的,且按照它们在类中出现的顺序进行初始化.在一个析构函数中,首先执行函数体,然后销毁成员.成员按

c++primer(第五版) 第十三章 拷贝控制习题答案

纯原创    转载请注明出处:http://blog.csdn.net/axuan_k 13.2    13.3   13.4    13.5 #include<iostream> using namespace std; class Point{ int a; }; Point global; //13.4 Point foo_bar(Point arg) //1 { Point local = arg, *heap = new Point(global); //2,3 *heap = lo