zoukankan      html  css  js  c++  java
  • 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 << "		" << contents  ;
        cout << "		" << folders.size()  << endl ;
    }
    void Folder::show() {
        cout << "		" << 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.运行结果:

    这里写图片描述

    这里写图片描述

  • 相关阅读:
    make、make clean、make install、make uninstall、make dist、make distcheck和make distclean
    Eclipse开发C/C++ 安装配置
    没有文件扩展“.js”的脚本引擎问题解决
    Linux目录架构详解
    Linux查看硬件信息以及驱动设备的命令
    23种设计模式彩图
    ACE在Linux下编译安装
    void及void指针含义的深刻解析
    centos7.x设置nginx开机自启动
    Centos7防火墙关闭和启用iptables操作
  • 原文地址:https://www.cnblogs.com/Tattoo-Welkin/p/10335296.html
Copyright © 2011-2022 走看看