练习13.33:
成员save是将本Message存放在给定的Folder中,成员remove是删除本Message,save/remove会调用insert函数/erase函数,如果不使用引用,直接使用Folder作为形参,那么save和remove中修改的是Folder的副本,函数运行结束,副本被释放,没有改变任何东西。由于需要删除对应Folder中的Message指针,即对Folder进行修改,所以不能使用const Folder&
练习13.34:
对Message进行定义,未定义Folder
#include <iostream>
#include <string>
using namespace std;
#include <vector>
#include <algorithm>
#include <set>
class Folder;
class Message {
friend class Folder;
friend void swap(Message& lhs, Message& rhs);
public:
//folders被隐式初始化为空集合
explicit Message(const std::string& str = ""):contents(str){ }
//拷贝构造成员,用来管理指向本Message的指针
//拷贝构造函数
Message(const Message&);
//拷贝赋值运算符
Message& operator=(const Message&);
~Message();
//从给定Folder集合中添加/删除本Message
void save(Folder&);
void remove(Folder&);
private:
//消息内容
std::string contents;
//包含message的Folder的set
std::set<Folder*>folders;
//拷贝构造函数,拷贝赋值运算符和析构函数所使用的工具函数
//将Message添加到指向参数的Folder中,Folder指向传递的参数,进行了拷贝,要添加一个Message进去,也就是本Message
void add_to_Folders(const Message&);
//从folders中的每一个Folder中删除Message,此Message是此对象的Message
void remove_from_Folders();
};
class Folder {
public:
void addMsg(Message* m);
void remMsg(Message* m);
};
void Message::save(Folder& f)
{
//将给定的Folder添加到我们的Folder列表中
folders.insert(&f);
//将本Message添加到f的Message集合中
f.addMsg(this);
}
void Message::remove(Folder& f)
{
//将给定Folder从我们的Folder列表中删除
folders.erase(&f);
//将本Message从f的Message集合中删除
f.remMsg(this);
}
//将本Message添加到指向m的Folder中
void Message::add_to_Folders(const Message& m)
{
//遍历每个包含m的Folder
for (auto f : m.folders)
{
//向每个Folder中添加一个指向本Message的指针
f->addMsg(this);
}
}
//Message的拷贝构造函数拷贝给定对象的数据成员
Message::Message(const Message& m) :contents(m.contents), folders(m.folders)
{
//拷贝构造完成后将本消息添加到指向m的Folder中
add_to_Folders(m);
}
//从对应的Folder中删除本Message
void Message::remove_from_Folders()
{
//遍历本Message中的所有Folder,把指向本Message的指针删除
for (auto f : folders)
{
f->remMsg(this);
}
}
//析构函数
Message::~Message()
{
remove_from_Folders();
}
//拷贝赋值运算符
Message& Message::operator=(const Message& rhs)
{
//先从左侧运算对象的folders中删除此Message的指针,然后再将指针添加到右侧运算对象的folders中
remove_from_Folders();
contents = rhs.contents;
folders = rhs.folders;
//将本Message添加到那些Folder中
add_to_Folders(rhs);
return *this;
}
//自定义的swap
void swap(Message& lhs, Message& rhs)
{
using std::swap;
//将每个消息的指针从它所在的Folder中删除
for (auto f : lhs.folders)
{
f->remMsg(&lhs);
}
for (auto f : rhs.folders)
{
f->remMsg(&rhs);
}
//交换contents和Folder指针set
swap(lhs.contents, rhs.contents);
//交换set&
swap(lhs.folders, rhs.folders);
//将每个Message的指针添加到它的(新)Folder中
for (auto f : lhs.folders)
{
f->addMsg(&lhs);
}
for (auto f : rhs.folders)
{
f->addMsg(&rhs);
}
}
int main()
{
system("pause");
return 0;
}
练习13.35:
Message成员中,contents为string类型,folders为set类型,标准库中都有自己的拷贝控制成员,对于这两个成员,使用合成的拷贝控制也能实现拷贝。但是拷贝完成后,我们还需要将拷贝后的Message添加到对应的Folder中,无法使用合成的版本来实现,需要我们自己定义
练习13.36:
Folder类实现如下:
//与Message基本类似,两者是对称的
class Folder {
friend class Message;
friend void swap(Message& lhs, Message& rhs);
public:
//默认构造函数
Folder(){ };
//拷贝构造函数
Folder(const Folder& f);
//拷贝赋值运算符
Folder& operator=(const Folder& f);
//析构函数
~Folder();
//Folder版本的save和remove函数
void save(Message&);
void remove(Message&);
private:
std::set<Message*>msg;
//与Message类似的两个添加删除工具函数
void add_to_Message(const Folder&);
void remove_from_Message();
//向msg中添加或删除一个给定的Message*
void addMsg(Message* m);
void remMsg(Message* m);
};
//向msg中添加或删除一个给定的Message*
void Folder::addMsg(Message* m)
{
msg.insert(m);
}
void Folder::remMsg(Message* m)
{
msg.erase(m);
}
//save成员函数
void Folder::save(Message& m)
{
msg.insert(&m);
//将本Folder添加到m的Folder集合中
m.addFolder(this);
}
//remove成员函数
void Folder::remove(Message& m)
{
msg.erase(&m);
//将本Folder从m的Folder集合中删除
m.remFolder(this);
}
//将本Folder添加到指向f的Message中
void Folder::add_to_Message(const Folder& f)
{
for (auto m : f.msg)
{
m->addFolder(this);
}
}
//Folder拷贝构造函数
Folder::Folder(const Folder& f) :msg(f.msg)
{
add_to_Message(f);
}
//从对应的Meesage指针集合中删除本Message
void Folder::remove_from_Message()
{
for (auto m : msg)
{
m->remFolder(this);
}
}
//析构函数
Folder::~Folder()
{
remove_from_Message();
}
//拷贝赋值运算符
Folder& Folder::operator=(const Folder& f)
{
remove_from_Message();
msg = f.msg;
add_to_Message(f);
return *this;
}
练习13.37:
两个成员函数为addFolder和remFolder,两成员函数实现如下所示
//addFolder实现
void Message::addFolder(Folder* f)
{
folders.insert(f);
}
//remFolder实现
void Message::remFolder(Folder* f)
{
folders.erase(f);
}
最终两个类的定义为:
#include <iostream>
#include <string>
using namespace std;
#include <vector>
#include <algorithm>
#include <set>
class Folder;
class Message {
friend class Folder;
friend void swap(Message& lhs, Message& rhs);
public:
//folders被隐式初始化为空集合
explicit Message(const std::string& str = ""):contents(str){ }
//拷贝构造成员,用来管理指向本Message的指针
//拷贝构造函数
Message(const Message&);
//拷贝赋值运算符
Message& operator=(const Message&);
~Message();
//从给定Folder集合中添加/删除本Message
void save(Folder&);
void remove(Folder&);
private:
//消息内容
std::string contents;
//包含message的Folder的set
std::set<Folder*>folders;
//拷贝构造函数,拷贝赋值运算符和析构函数所使用的工具函数
//将Message添加到指向参数的Folder中,Folder指向传递的参数,进行了拷贝,要添加一个Message进去,也就是本Message
void add_to_Folders(const Message&);
//从folders中的每一个Folder中删除Message,此Message是此对象的Message
void remove_from_Folders();
//与addMsg和remMsg类似的成员函数
void addFolder(Folder*);
void remFolder(Folder*);
};
//与Message基本类似,两者是对称的
class Folder {
friend class Message;
friend void swap(Message& lhs, Message& rhs);
public:
//默认构造函数
Folder(){ };
//拷贝构造函数
Folder(const Folder& f);
//拷贝赋值运算符
Folder& operator=(const Folder& f);
//析构函数
~Folder();
//Folder版本的save和remove函数
void save(Message&);
void remove(Message&);
private:
std::set<Message*>msg;
//与Message类似的两个添加删除工具函数
void add_to_Message(const Folder&);
void remove_from_Message();
//向msg中添加或删除一个给定的Message*
void addMsg(Message* m);
void remMsg(Message* m);
};
//向msg中添加或删除一个给定的Message*
void Folder::addMsg(Message* m)
{
msg.insert(m);
}
void Folder::remMsg(Message* m)
{
msg.erase(m);
}
//save成员函数
void Folder::save(Message& m)
{
msg.insert(&m);
//将本Folder添加到m的Folder集合中
m.addFolder(this);
}
//remove成员函数
void Folder::remove(Message& m)
{
msg.erase(&m);
//将本Folder从m的Folder集合中删除
m.remFolder(this);
}
//将本Folder添加到指向f的Message中
void Folder::add_to_Message(const Folder& f)
{
for (auto m : f.msg)
{
m->addFolder(this);
}
}
//Folder拷贝构造函数
Folder::Folder(const Folder& f) :msg(f.msg)
{
add_to_Message(f);
}
//从对应的Meesage指针集合中删除本Message
void Folder::remove_from_Message()
{
for (auto m : msg)
{
m->remFolder(this);
}
}
//析构函数
Folder::~Folder()
{
remove_from_Message();
}
//拷贝赋值运算符
Folder& Folder::operator=(const Folder& f)
{
remove_from_Message();
msg = f.msg;
add_to_Message(f);
return *this;
}
/
void Message::save(Folder& f)
{
//将给定的Folder添加到我们的Folder列表中
folders.insert(&f);
//将本Message添加到f的Message集合中
f.addMsg(this);
}
void Message::remove(Folder& f)
{
//将给定Folder从我们的Folder列表中删除
folders.erase(&f);
//将本Message从f的Message集合中删除
f.remMsg(this);
}
//将本Message添加到指向m的Folder中
void Message::add_to_Folders(const Message& m)
{
//遍历每个包含m的Folder
for (auto f : m.folders)
{
//向每个Folder中添加一个指向本Message的指针
f->addMsg(this);
}
}
//Message的拷贝构造函数拷贝给定对象的数据成员
Message::Message(const Message& m) :contents(m.contents), folders(m.folders)
{
//拷贝构造完成后将本消息添加到指向m的Folder中
add_to_Folders(m);
}
//从对应的Folder中删除本Message
void Message::remove_from_Folders()
{
//遍历本Message中的所有Folder,把指向本Message的指针删除
for (auto f : folders)
{
f->remMsg(this);
}
}
//析构函数
Message::~Message()
{
remove_from_Folders();
}
//拷贝赋值运算符
Message& Message::operator=(const Message& rhs)
{
//先从左侧运算对象的folders中删除此Message的指针,然后再将指针添加到右侧运算对象的folders中
remove_from_Folders();
contents = rhs.contents;
folders = rhs.folders;
//将本Message添加到那些Folder中
add_to_Folders(rhs);
return *this;
}
//自定义的swap
void swap(Message& lhs, Message& rhs)
{
using std::swap;
//将每个消息的指针从它所在的Folder中删除
for (auto f : lhs.folders)
{
f->remMsg(&lhs);
}
for (auto f : rhs.folders)
{
f->remMsg(&rhs);
}
//交换contents和Folder指针set
swap(lhs.contents, rhs.contents);
//交换set&
swap(lhs.folders, rhs.folders);
//将每个Message的指针添加到它的(新)Folder中
for (auto f : lhs.folders)
{
f->addMsg(&lhs);
}
for (auto f : rhs.folders)
{
f->addMsg(&rhs);
}
}
//addFolder实现
void Message::addFolder(Folder* f)
{
folders.insert(f);
}
//remFolder实现
void Message::remFolder(Folder* f)
{
folders.erase(f);
}
int main()
{
system("pause");
return 0;
}
练习13.38:
这样做也可以达到与我们这里使用的方法一样的效果,但是rhs的一些创建销毁毫无意义,只会使得效率低下,使用我们的方法就可以避免不必要的拷贝操作,性能更高