Message类 + Folder类
#include#include #include #include #include using namespace std; class Folder; class Message { friend class Folder; friend ostream& operator<<(ostream&, const Message&); friend void swap(Message&, Message&); public: explicit Message(const string& s = string()) :contents(s), Folders(set ()) {} Message(const Message&); Message& operator=(const Message&); ~Message(); // 这两个才是一般情况下使用的成员函数 保存/移除 void save(Folder&); void remove(Folder&); private: string contents; set Folders; // 拷贝成员,析构函数需要用的工具函数 void add_to_Folders(const Message&); void remove_from_Folders(); // 双向删除 // used by Folder class to add self to this Message's set of Folder's void addFloder(Folder* f) { Folders.insert(f); } void removeFolder(Folder* f) { Folders.erase(f); } }; class Folder { friend void swap(Message&, Message&); friend Message; public: Folder() = default; Folder(const Folder&); ~Folder(); Folder& operator=(const Folder&); void save(Message& m) { Msgs.insert(&m); m.addFloder(this); } void remove(Message& m) { Msgs.erase(&m); m.removeFolder(this); } private: set Msgs; // 拷贝成员,以及析构函数所需要的工具函数 void add_to_Messages(const Folder&); void remove_from_Msgs(); //双向删除,不同于Message的 // void addMsg(Message* pm) { Msgs.insert(pm); } void removeMsg(Message* pm) { Msgs.erase(pm); } }; void Folder::add_to_Messages(const Folder& f) { for (auto& i : f.Msgs) i->addFloder(this); } void Folder::remove_from_Msgs() { while (!Msgs.empty()) (*Msgs.begin())->remove(*this); } Folder::Folder(const Folder& f):Msgs(f.Msgs) { add_to_Messages(f); } Folder::~Folder() { remove_from_Msgs(); } Folder& Folder::operator=(const Folder& f) { remove_from_Msgs(); Msgs = f.Msgs; add_to_Messages(f); return *this; } //`````````````````````````````````````````````````````````` void Message::save(Folder& f) { Folders.insert(&f); f.addMsg(this); } void Message::remove(Folder& f) { Folders.erase(&f); f.removeMsg(this); } void Message::add_to_Folders(const Message& m) { for (auto& i : m.Folders) i->addMsg(this); // i是Folder* } void Message::remove_from_Folders() { for (auto& i : Folders) i->removeMsg(this); Folders.clear(); } Message::Message(const Message& m):Folders(m.Folders),contents(m.contents) { add_to_Folders(m); } Message::~Message() { remove_from_Folders(); } Message& Message::operator=(const Message& m) { remove_from_Folders(); Folders = m.Folders; contents = m.contents; add_to_Folders(m); return *this; } ostream& operator<<(ostream& os, const Message& m) { os << m.contents; return os; } void swap(Message& lhs, Message& rhs) { using std::swap; cout << "???????????" << endl; for (auto& i : lhs.Folders) i->removeMsg(&lhs); for (auto& i : rhs.Folders) i->removeMsg(&rhs); swap(lhs.contents, rhs.contents); swap(lhs.Folders, rhs.Folders); for (auto& i : lhs.Folders) i->addMsg(&lhs); for (auto& i : rhs.Folders) i->addMsg(&rhs); } int main() { Message m1("111"); Message m2("222"); Message m3("333"); Message m4("444"); Folder f1; Folder f2; m1.save(f1); m2.save(f1); m3.save(f2); m4.save(f2); m1 = m3; cout << &m2 << endl; cout << &m4 << endl; swap(m2, m4); cout << &m2 << endl; cout << &m4 << endl; return 0; }
真他妈的快吐了,这个b东西。起初13.4的初衷只是为了举出一个例子:即资源管理并不是一个类需要定义自己的拷贝控制成员的唯一原因。而Message和Folder类就是一个例子,这个类如果仅考虑拷贝构造,以及赋值运算符的本质工作是完全可以的,但是这两个类需要互相进行薄记工作,即Folder中保存着若干Message,就类似于信息以及信息列表。所以当一条信息销毁时,对应的信息列表也应该删除对这个信息的记录,即Folder中的set
应该删除对应的Message*。
两个类的组成非常相似,如Message类 其中的private成员中有两个函数是用来辅助自己的拷贝成员及析构函数的工作的,即:add_to_Folders 辅助拷贝构造函数和拷贝赋值运算符。remove_from_Folders 辅助析构函数和拷贝赋值运算符。如旧,拷贝赋值运算符结合了析构和拷贝构造的任务。
而另外两个私有成员函数是为了辅助另一个类的一些成员函数完成工作的。
对于swap函数有一种错误的写法
void swap(Message& lhs, Message& rhs)
{
using std::swap;
lhs.remove_from_Folders();
rhs.remove_from_Folders();
lhs.add_to_Folders(rhs);
rhs.add_to_Folders(lhs);
swap(lhs.contents, rhs.contents);
swap(lhs.Folders, rhs.Folders);
}
错误的原因是remove函数是双向删除的,即当lhs和rhs执行完remove之后,它们的Folders中并不存储着原来的Folder*了。而正确的做法就是利用Folder中的两个私有成员函数来实现。



