C++ Primer 第十三章 13.4 拷貝控制示例 練習和總結

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。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章