Best Practices:拷贝赋值运算符通常执行拷贝构造函数和析构函数中也要做的工作。这种情况下,公共的工作应该放在private的工具函数中完成。
#include<iostream>
#include<string>
#include<set>
using namespace std;
class Message;
class Folder {
public:
void addMsg(Message* msg) {
Msg.insert(msg);
}
void remMsg(Message* msg) {
Msg.erase(msg);
}
private:
set<Message*> Msg;
};
class Message {
friend class Folder;
public:
//显示构造函数,有一个默认参数,也是默认构造函数
//因为调用set,所以folders被隐式初始化为空集
explicit Message(const string& str = "") :contents(str) {};
//拷贝构造函数
Message(const Message&);
//拷贝赋值函数
Message& operator=(const Message&);
~Message();
//将Message存放到指定Folder之中
void save(Folder&);
void remove(Folder&);
private:
string contents;
set<Folder*> folders;
void add_to_folders(const Message&);
void remove_from_folders();
void swap(Message& lhs, Message& rhs);
};
//从Msg添加指针到folders中
void Message::save(Folder& f) {
folders.insert(&f);
f.addMsg(this);
}
void Message::remove(Folder& f) {
folders.erase(&f);
f.remMsg(this);
}
//拷贝的时候是两个msg,要把其中一个msg的每一个folders都添加另一个msg,即this
void Message::add_to_folders(const Message& msg) {
for (auto f : msg.folders)
f->addMsg(this);
}
//删除folder中本Message
void Message::remove_from_folders() {
for (auto f : folders)
f->remMsg(this);
}
//拷贝构造函数
Message::Message(const Message& msg) :contents(msg.contents),folders(msg.folders){
add_to_folders(msg);
}
//拷贝赋值函数 -->执行拷贝构造和析构
Message& Message::operator=(const Message& msg) {
remove_from_folders();
contents = msg.contents;
folders = msg.folders;
add_to_folders(msg);
return *this;
}
Message::~Message() {
remove_from_folders();
}
//使用swap完成不必要的拷贝
void Message::swap(Message& lhs, Message& rhs) {
using std::swap;
for (auto f : lhs.folders) {
f->remMsg(&lhs); //从folders删除本Msg
}
for (auto f : rhs.folders) {
f->remMsg(&rhs); //从folders删除本Msg
}
swap(lhs.contents, rhs.contents);
swap(lhs.folders, rhs.folders);
for (auto f : lhs.folders) {
f->addMsg(&lhs);
}
for (auto f : rhs.folders) {
f->addMsg(&rhs);
}
}