首先解释一下什么是拷贝控制 ?其实就是拷贝构造函数、赋值操作符和析构函数这三种函数 . 那么如何编写这三个函数就叫做拷贝控制了.
1.整体需求 :
总共设计两个类:
1.一个是Message,代表电子邮件消息(或者其它)
2.一个是Folder ,代表消息目录
用生活中最一般的想法去思考,每一个消息目录中可以有许多消息(也可以有相同消息) , 每一条消息也可以出现在多个目录中 如下图所示 :
2 .程序架构设计 :
1. 记录Message在哪个Folder 中,记录Folder中有哪些Message ?
在 Message 中保存一个它所在的 Folder 的指针的set 集合 .(也就是说每一个Message中都有一个set集合) 同样的,在 Folder 中保存一个它包含的Message 的指针的set 集合 .
2. 删除一条 Message 时如何处理 ?
当我们删除一条 Message 时 ,我们需要考虑的是如何去删除其他目录中的该条消息,那么我们就需要从包含此消息的所有Folder中删除指向此 Message 的指针 .
3. 添加一条 Message 时如何处理 ?
创建一条Message(指明内容,但不用指明目录) , 创建完成后调用 save 在特定目录中存放 .
4.拷贝一条 Message 时如何处理 ?
拷贝消息内容和 set 集合 (因为都在相同的Folder下,所以Message中的set集合是不变的),但是我们必须在每个包含此消息的Folder中添加一个指向新创建的Message 的指针 因为虽然它们长得都一样,但是他们就是两个不同的对象 .
5. Message 对象之间赋值时怎么办 ?
更新 Folder 集合 ,从包含左侧Message的所有Folder 中将其删除 , 添加它到包含右侧Message 的Folder中 .
3.实现代码:
/*myhead.h 文件*/
#ifndef _MYHEAD_H
#define _MYHEAD_H
#include<iostream>
#include<string>
#include<set>
#include<vector>
class Folder ;
class Message {
friend class Folder ;
friend void swap(Message &,Message &) ;
public:
explicit Message(const std::string &str=""):contents(str){ }
//拷贝控制成员 ,用来管理指向本 Message 的指针
//拷贝构造函数
Message(const Message &);
//拷贝赋值运算符
Message& operator=(const Message &);
~Message() ;
//从给定的 Folder 中添加/删除 Message
void save(Folder & );
void remove(Folder &);
// //在该目录下添加一条 Message 或者 删除一条 Message
void addFolder(Folder *m) { folders.insert(m); }
void remFolder(Folder *m) { folders.erase(m); }
void show() ;
private:
std::string contents ; // 实际消息文本
std::set<Folder *> folders ; //目录指针
void add_to_Folders(const Message & );
void remove_form_Folders() ;
};
void swap(Message &lhs ,Message &rhs) ;
class Folder {
friend class Message ;
friend void swap(Folder &,Folder &) ;
public:
Folder() = default ;
Folder(const Folder & );
Folder& operator=(const Folder &);
~Folder() ;
void show() ;
void save(Message &TT) ;
// //在该目录下添加一条 Message 或者 删除一条 Message
void addMsg(Message *m) { messages.insert(m); }
void remMsg(Message *m) { messages.erase(m); }
private:
std::set<Message *> messages ;
void add_to_Message(const Folder & ) ;
void remove_form_Message() ;
};
void swap(Folder &,Folder &) ;
#endif
/*函数实现*/
#include"myhead.h"
using namespace std ;
//将本 Messgae 添加到指向m的 Folder 中
void Message::add_to_Folders( const Message &m ) {
for(auto f : m.folders )
f->addMsg(this);
}
void Folder::add_to_Message( const Folder &f) {
for(auto m :f.messages )
m->addFolder( this );
}
void Message::remove_form_Folders( ){
for(auto f : folders )
f->remMsg(this);
}
void Folder::remove_form_Message( ) {
for(auto f : messages )
f->remFolder( this );
}
void Message::show( ){
cout << "\t\t" << contents ;
cout << "\t\t" << folders.size() << endl ;
}
void Folder::show() {
cout << "\t\t" << messages.size() << endl ;
}
void Folder::save( Message &TT) {
addMsg(&TT);
}
Message::Message(const Message &m){
contents = m.contents ;
folders = m.folders ;
add_to_Folders(m) ;
}
//拷贝赋值运算符
Message& Message::operator=(const Message &rhs){
remove_form_Folders();
contents = rhs.contents ;
folders = rhs.folders ;
add_to_Folders(rhs) ;
return *this ;
}
Message::~Message() { //析构函数
remove_form_Folders() ;
}
//从给定的 Folder 中添加/删除 Message
void Message::save(Folder &f){
folders.insert(&f) ; //将 f 加入我们的 Message 中
f.addMsg(this) ; //将 this 对象加入 f 中
}
void Message::remove(Folder &f){
folders.erase(&f) ;
f.remMsg(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);
}
Folder::Folder(const Folder &f){ // 目录复制
messages = f.messages ;
add_to_Message(f) ; //将该目录加入到 Messagees 中
}
Folder& Folder::operator=(const Folder &rhs){
remove_form_Message();
messages = rhs.messages ;
add_to_Message(rhs);
return *this ;
}
Folder::~Folder(){
remove_form_Message();
}
void swap(Folder &lhs ,Folder &rhs ){
using std::swap ;
for(auto f: lhs.messages )
f->remFolder( &lhs );
for(auto f: rhs.messages)
f->remFolder(&rhs);
swap(lhs.messages , rhs.messages );
for(auto f: lhs.messages)
f->addFolder(&lhs);
for(auto f: rhs.messages)
f->addFolder(&rhs);
}
/*main 函数*/
#include"myhead.h"
using namespace std ;
int main(void )
{
string s1("cutter_point1");
string s2("cutter_point2");
string s3("cutter_point3");
string s4("cutter_point4");
string s5("cutter_point5");
string s6("cutter_point6");
// all new messages, no copies yet
Message m1(s1);
Message m2(s2);
Message m3(s3);
Message m4(s4);
Message m5(s5);
Message m6(s6);
Folder f1;
Folder f2;
m1.save(f1); m3.save(f1);m5.save(f1);
m1.save(f2);
m2.save(f2); m4.save(f2); m6.save(f2);
cout<<"f1到f2中 Message 的个数:"<<endl;
f1.show(); f2.show() ; //should is 3 ,4
cout<<"m1到m6中folders的个数:"<<endl;
m1.show(); m2.show(); m3.show(); //should is 2,1,1,1,1,1
m4.show(); m5.show(); m6.show();
// create some copies
Message c1(m1);
Message c2(m2), c4(m4), c6(m6) ;
cout<<"f1到f2中 Message 的个数:"<<endl;
f1.show(); f2.show() ; //should is 4 , 8
cout<<"c1,c2,c4,c6 中folders的个数:"<<endl;
c1.show(); c2.show(); c4.show(); //should is 2,1,1,1
c6.show();
// finally, self-assignment
m2 = m2;
m1 = m1;
// now some assignments
m2 = m3;
m4 = m5;
m6 = m3;
m1 = m5;
cout<<"f1到f2中 Message 的个数:"<<endl;
f1.show(); f2.show() ; //should is 7,4 ,这里可能需要动动脑筋想一下是为什么哦
cout<<"m1到m6中folders的个数:"<<endl;
m1.show(); m2.show(); m3.show(); //should is 1,1,1,1,1,1
m4.show(); m5.show(); m6.show();
cout<<"c1,c2,c4,c6 中folders的个数:"<<endl;
c1.show(); c2.show(); c4.show(); //should is 2,1,1,1
c6.show();
Folder f3;
f3.save(c1) ;
f3.save(c4) ;
f3.save(c6) ;
Folder f4 = f3 ;
cout<<"c1,c4,c6 中folders的个数:"<<endl;
c1.show(); //should is 3,2,2
c4.show();
c6.show();
cout<<"f3 ,f4中 Message 的个数:"<<endl;
f3.show(); f4.show() ; //should is 3,3
return 0;
}