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。

但是这样不是可以简化赋值语句的操作么,如果这里的受益指的是性能上的提升,那么没什么受益,但是从代码重用的角度来看,还是受益了

发布了54 篇原创文章 · 获赞 6 · 访问量 3299

猜你喜欢

转载自blog.csdn.net/zengqi12138/article/details/104500776