13.4 拷贝控制示例
练习
13.33
因为如果形参类型是const Folder&,那边形参是一个常量。
那么folders的类型必须是常量指针。
那么调用的Folder的AddMsg和remMsg就必须是常量函数。
而这两个函数肯定会修改Folder中数据成员的值,因此不能被设置为常量函数。
所以只能讲save和remove的形参定义为非const类型。
13.34
class Message {
friend class Folder;
public:
friend void swap(Message& lhs, Message& rhs);
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& m);
void remove_from_Folders();
};
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) {
using std::swap;
for (auto f : lhs.folders) {
f->remMsg(&lhs);
}
for (auto f:rhs.folders) {
f->remMsg(&rhs);
}
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);
}
}
13.35
那么通过拷贝初始化生成的对象的folders成员所指向的Floder对象中将不会有本对象的指针。
13.36
这里设计的Folder,按照的是Message的设计思路,所有的函数基本都是一样的。
但是为了方便辨认,加了一个name成员,用于保存对象的名字。
但是这样的设计导致了一个问题,如果从Folder中添加Message,那么除了需要设计另外一个添加的函数,因为Message中调用了addMsg(),如果在addMsg()使用m->save()那么save()又会调用addMsg(),如此一来就死循环了。
所以我直接假定,只能把Message加到Folder中,而不能让Folder主动加。代码如下面的第二个代码
class Message;
class Folder {
public:
friend class Message;
void addMsg(Message *);
void remMsg(Message *);
Folder(string str):name(str){};
Folder(const Folder& f);
Folder& operator=(const Folder&f);
~Folder();
private:
string name;
set<Message*> messages;
void add_to_messages(const Folder&);
void remove_from_messages();
};
void Folder::addMsg(Message * m) {
messages.insert(m);
}
void Folder::remMsg(Message *m) {
messages.erase(m);
}
Folder::Folder(const Folder& f):name(f.name),messages(f.messages) {
add_to_messages(f);
}
Folder& Folder::operator=(const Folder&f) {
remove_from_messages();
name = f.name;
messages = f.messages;
add_to_messages(f);
return *this;
}
Folder::~Folder() {
remove_from_messages();
}
void Folder::add_to_messages(const Folder& f) {
for (const auto m:f.messages) {
m->save(*this);
}
}
void Folder::remove_from_messages() {
for (const auto m:messages) {
m->remove(*this);
}
}
class Message;
class Folder {
public:
friend class Message;
void addMsg(Message *);
void remMsg(Message *);
Folder(string str):name(str){};
Folder(const Folder& f)=delete;
Folder& operator=(const Folder&f)=delete;
//~Folder();
private:
string name;
set<Message*> messages;
};
///////////////// Folder
// 这里的addMsg和Message的save是不一样的,这里的addMsg仅用来
void Folder::addMsg(Message * m) {
messages.insert(m);
//m->save();
}
//同理这里也不要调用m->remove()
void Folder::remMsg(Message *m) {
messages.erase(m);
}
13.37
void addFolder(Folder* f) {
folders.insert(f);
};
void removeFolder(Folder* f) {
folders.erase(f);
}
13.38
我觉得是可以的,但是参考其余的答案说,因为不涉及动态内存的分配,所以不能从swap中得到受益,所以不使用swap。
但是这样不是可以简化赋值语句的操作么,如果这里的受益指的是性能上的提升,那么没什么受益,但是从代码重用的角度来看,还是受益了