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。
但是這樣不是可以簡化賦值語句的操作麼,如果這裏的受益指的是性能上的提升,那麼沒什麼受益,但是從代碼重用的角度來看,還是受益了