C++ primer之拷贝控制示例

首先解释一下什么是拷贝控制 ?其实就是拷贝构造函数、赋值操作符和析构函数这三种函数 . 那么如何编写这三个函数就叫做拷贝控制了.

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;  
} 

4.运行结果:

这里写图片描述

这里写图片描述

posted @ 2018-04-18 21:23  Tattoo_Welkin  阅读(254)  评论(0编辑  收藏  举报