您的位置:首页 > 编程语言 > C语言/C++

C++基础—消息处理实例

2014-09-29 11:44 239 查看
有些类为了做一些工作需要对复制进行控制。

Message类和Folder类分别表示电子邮件(或其他)消息和消息所出现的目录,一个给定消息可以出现在多个目录中。Message上有 save和 remove操作,用于在指定Folder中保存或删除该消息。

数据结构:

对每个Message,我们并不是在每个Folder中都存放一个副本,而是使每个Message保存一个指针集(set),set中的指针指向该Message所在的Folder。每个Folder也保存着一些指针,指向它所包含的Message。数据结构如图所示。



操作:

创建新的Message时,将指定消息的内容但不指定Folder。调用save将 Message放入一个Folder。

复制一个Message对象时,将复制原始消息的内容和Folder指针集,还必须给指向源 Message的每个Folder增加一个指向该Message的指针。

将一个Message对象赋值给另一个,类似于复制一个Message:赋值之后,内容和 Folder集将是相同的。首先从左边Message在赋值之前所处的Folder中删除该Message。原来的Message去掉之后,再将右边操作数的内容和Folders集复制到左边,还必须在这个Folder集中的每个Folders中增加一个指向左边Message的指针。

撤销一个Message对象时,必须更新指向该Message的每个 Folder。一旦去掉了 Message,指向该Message的指针将失效,所以必须从该Message的Folder指针集的每个Folder中删除这个指针。

可以看到,析构函数和赋值操作符分担了从保存给定Message的 Folder列表中删除消息的工作。类似地,复制构造函数和赋值操作符分担将一个Message加到给定Folder列表的工作。我们将定义一对private实用函数完成这些任务。

下面是实现的代码:

#include <iostream>
#include <string>
#include <set>

using namespace std;

class Message;  //<需要先声明,才能在Folder中使用
class Folder
{
	Folder(){};
	~Folder();
	void addMsg(Message *);
	void remMsg(Message *);
private:
	set<Message *> messages;
	void remove_Fldr_form_Messages();

};
class Message
{
public:
	Message (const string &str = ""):contents(str){};   //<复制构造函数,初始化列表
	Message (const Message &); //<构造函数
	Message &operator= (const Message &); //<赋值操作符
	~Message();

	void save(Folder &);
	void remove(Folder &);
	void addFldr(Folder *);
	void remFldr(Folder *);
private:
	string contents;
	set<Folder *> folders;
	void put_Msg_in_Folders(const set<Folder *> &rhs);//自身Message的一个副本添加到指向给定Message的各Folder中
	void remove_Msg_from_Folders();//从folders成员的每个Folder中删除指向这个Message的指针

};
void Message::save(Folder &f)
{
	folders.insert(&f);//<更新message对应目录
	f.addMsg(this);    //<增加目录中对应的此条目录
}
void Message::remove(Folder &f)
{
	folders.erase(&f); //<删除此消息对应的这个目录 ,folders是这条消息对应的目录集合
	f.remMsg(this);    //<删除这个目录中对应的此条内容
}
void Message::addFldr(Folder *f)
{
	folders.insert(f);
}
void Message::remFldr(Folder *f)
{
	folders.erase(f);
}
void Message::put_Msg_in_Folders(const set<Folder *> &rhs)
{
	for (set<Folder *>::const_iterator beg = rhs.begin(); beg != rhs.end(); ++beg)
	{
		(*beg)->addMsg(this); //<在对应的目录中加入这条消息
	}
}
void Message::remove_Msg_from_Folders() //<在对饮目录中删除这条消息
{
	for (set<Folder *>::const_iterator beg = folders.begin(); beg != folders.end(); ++beg)
	{
		(*beg)->remMsg(this);
	}
}
/************************************************************************/
/* 赋值时需删除左操作数,并在撤销左操作数的成员之后,
将右操作数的成员赋值给左操作数的相应成员。
如果对象是相同的,则撤销左操作数的成员也将撤销右操作数的成员!                                                                     */
/************************************************************************/
Message& Message::operator=(const Message &rhs)
{
	if (&rhs != this)
	{
		remove_Msg_from_Folders();
		contents = rhs.contents;
		folders = rhs.folders;
		put_Msg_in_Folders(rhs.folders);
	}
	return * this;
}

/************************************************************************/
/* 系统自动调用string析构函数释放contents,
自动调用set析构函数清除用于保存folders成员的内存,
因此,Message析构函数唯一要做的是调用remove_Msg_from_Folders                                                                     */
/************************************************************************/
Message:: ~Message()
{
	remove_Msg_from_Folders();
}

//------------------------------------------------------------------------------------------
Folder::~Folder()
{
	remove_Fldr_form_Messages();
}
void Folder::addMsg(Message *rhs)
{
	messages.insert(rhs);
}
void Folder::remMsg(Message *rhs)
{
	messages.erase(rhs);
}
void Folder::remove_Fldr_form_Messages()  
{  
	for (std::set<Message *>::const_iterator beg = messages.begin();  
		beg != messages.end(); ++beg)  
	{  
		(*beg) -> remFldr(this);  
	}  
}
赋值操作符通常需要做复制构造函数函数和析构函数也要完成的工作。在这种情况下,通用工作应该放在private实用函数中。

复制构造函数将用旧对象成员的副本初始化新对象的数据成员。除了这些初始化之外(合成复制构造函数可以完成这些初始化),还必须用folders进行迭代,将这个新的Message加到那个集的每个Folder中。复制构造函数使用put_Msg_in_Folder函数完成这个工作。

编写自己的复制构造函数时,必须显式复制需要复制的任意成员。显式定义的复制构造函数不会进行任何自动复制

像其他任何构造函数一样,如果没有初始化某个类成员,则那个成员用该成员的默认构造函数初始化。复制构造函数中的默认初始化不会使用成员的复制构造函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: