C++ Primer消息处理示例

例子:

对于邮件处理应用程序,Message类和Folder类分别表示电子邮件消息和消息出现的目录,一个给定的消息可以出现在多个目录中。

Message和Folder类设计如图:


对于每个Message,我们并不是在每个Folder中都存放一个副本,而是使每个Message保存一个指针集setset中的指针指向该Message所在的Folder。每个Folder中也有一个指针集,其中的指针指向它所包含的Message

 

1.所以对于Message类,它有私有的成员:

set<Folder*> folders,用于保存指向它所在Folder的指针。

string contents,用于保存消息内容。

 

对于Folder类,它有私有成员:

Set<Message*>messages,用于保存指向它所包含的Message的指针。

 

 

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

在创建新的Message对象时,需要调用接受单个string形参的构造函数如下:

Message(const string str="") : contents(str){}

构造函数将消息的副本保存在contents中,并将set<Folder*> folders隐式初始化为空集,因为这个构造函数提供一个默认实参(空串),所以它也可以作为默认构造函数。

 

创建新的Folder对象时,调用的默认构造函数如下:

Folder(){}

 

 

3.当复制一个Message对象时,将复制原始消息的内容和Folder指针集,还必须给指向源Message的每个Folder增加一个指向该Message的指针,这个过程用put_Msg_in_Folders(const set<Folder*>&)来实现,这个成员函数是私有的,因为客户程序不需要调用到它。

Message::Message(Message &m): contents(m.contents), folders(m.folders)

{

      put_Msg_in_Folders(folders);

}

 

void Message::put_Msg_in_Folders(constset<Folder*>&rhs)

{

      for (set<Folder*>::const_iterator beg=rhs.begin();

            beg!=rhs.end(); ++beg)

            (*beg)->addMsg(this);

}

其中addMsgFolder类的public成员函数,用于将Message对象的指针加入到Folder类对象的messages成员变量中。

void Folder::addMsg(Message*msg)

{

      messages.insert(msg);

}

 

当复制一个Folder对象时,不仅要复制成员messages,还要在源Folder所指向的每一个Message对象的folders成员中增加自己的this指针。这个功能使用void put_Foldr_in_Msgs(constset<Message*>&)这个私有的函数来完成。

Folder::Folder(const Folder &f) : messages(f.messages)

{

      put_Foldr_in_Msgs(messages);

}

 

void Folder::put_Foldr_in_Msgs(constset<Message*>&msg)

{

      for (set<Message*>::const_iterator beg=msg.begin();

            beg!=msg.end(); ++beg)

            (*beg)->addFldr(this);

}

其中的addFldr是Message的成员函数,用于将Folder对象的指针加到Message对象的folders成员变量中去。

void Message::addFldr(Folder*f)

{

      folders.insert(f);

}

 

 

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

Message& Message::operator=(const Message &msg)

{

      if (&msg!=this) {

            remove_Msg_from_Folders();

            contents= msg.contents;

            folders= msg.folders;

            put_Msg_in_Folders(msg.folders);

      }

      return *this;

}

其中emove_Msg_from_Folders()用于将左边Message对象从所有包含它的Folder中删除。用if做判断的原因是若不判断,如果出现左右操作数相同的情况。则folders = msg.folders这一步得到的folders就不正确了。

void Message::remove_Msg_from_Folders()

{

      for (set<Folder*>::const_iterator beg=folders.begin();

            beg!=folders.end();++beg)

            (*beg)->removeMsg(this);

}

其中void removeMsg(Message*)用于删除Folder对象messages成员中的Message对象。

void Folder::removeMsg(Message*msg)

{

      messages.erase(msg);

}

 

同理,将Folder对象赋值给另一个是一样的操作。

Folder& Folder::operator=(const Folder &f)

{

      if (&f!=this) {

            remove_Fldr_from_Msgs();

            messages= f.messages;

            put_Fldr_in_Msgs(f.messages);     

      }

      return *this;

}

其中remove_Fldr_from_Msgs()用于将左边Folder对象从所有包含它的Message中删除。

void Folder::remove_Fldr_from_Msgs()

{

      for (set<Message*>::const_iterator beg=messages.begin();

            beg!=messages.end();++beg)

            (*beg)->removeFldr(this);

}

其中void removeFldr(Folder*)用于删除Message对象folders成员中的Folder对象。

void Message::removeFldr(Folder*f)

{

      folders.erase(f);

}

 

5.Message析构函数:

~Message()

      {

            remove_Msg_from_Folders();

      }

有了remove_Msg_from_Folders()函数,编写析构函数将非常简单。我们调用remove_Msg_from_Folders()函数清除folders,系统自动调用string析构函数释放contents,自动调用set析构函数清除用于保存folders成员的内存清除用于保存folders成员的内存。因此,Message析构函数唯一要做的是调用remove_Msg_from_Folders()。

对于Folder类是同理的。

 

6.对于一些保存和删除操作:在创建新Message对象时指定消息内容但不指定Folder。调用saveMessage放入一个Folder,调用remove将其从一个Folder中移除。

void Message::save(Folder&f)

{

      addFldr(&f);

      f.addMsg(this);

}

 

void Message::remove(Folder&f)

{

      removeFldr(&f);

      f.removeMsg(this);

}

 

void Folder::save(Message&msg)

{

      addMsg(&msg);

      msg.addFldr(this);

}

 

void Folder::remove(Message&msg)

{

      removeMsg(&msg);

      msg.removeFldr(this);

}

其实,其中额各种关系还是挺复杂的~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值