• C++primer 阅读点滴记录(一)


    第十三章 复制控制:(copy control)

         复制构造函数(copy constructor)

         复制操作符(assignment operator)

      ps: 什么时候需要显示的定义复制控制操作:类具有指针成员,一般情况使用默认的复制控制

             有的类 需要禁止复制构造函数, iostream类就不允许复制

            类必须显示的声明其复制构造函数为private

    最佳实践: 一般来说,最好显示或隐式定义默认构造函数和复制构造函数,只有不存在其他构造函数是才合成默认构造函数,如果定义了复制构造函数,也必须定义默认构造函数

    //示例代码:
    //copy constructor :
      Sales_item(const Sales_item& orig):
            isbn(orig.isbn),
            units_sold(orig.units_sold),
            revenue(orig.revenue){}
    //assignment operator:
      Sales_item& operator=(const Sales_items& rhs)
    
    
    Sales_item& Sales_item::operator=(const Sales_item& rhs){
        isbn = rhs.isbn;
        units_sold = rhs.units_sold;
        revenue = rhs.revenue;
        return *this;
    }
    注解: 实际上,应该将复制和赋值两个操作看作一个单元。 如果需要其中一个,我们几乎也肯定需要另一个。

      13.3 析构函数(destructor)

       何时调用析构函数:

    /*
     * 撤销类对象时会自动调用析构函数
     * 动态分配的对象只有在指向该对象的指针被删除时才撤销
     */
    void destructor_test(){
        Sales_item* p = new Sales_item; 
        {//new scope
            Sales_item item(*p);//copy constructor copies *p into item
            delete p;//destructor called on object pointed to by p
        }//exit local scope; destructor called on item
    }
    提示: 如果类需要析构函数,则它也需要赋值操作符和复制构造函数,这是一个有用的经验法则。这个规则常称为三法则(rule of three),指的是如果需要析构函数,则需要所有这三个幅值控制成员。
    注解: 撤销内置类型成员或复合类型的成员没什么影响。 尤其是,合成析构函数并不删除指针成员所指向的对象。(ps:所以 有指针对象成员的类 需要析构函数,需要复制构造函数 赋值操作符)

    消息实例  演示复制控制

    #ifndef MESSAGE_H
    #define MESSAGE_H
    #pragma once
    #include <string>
    #include <iostream>
    #include <set>
    
    using namespace std;
    
    class Message;
    
    class Folder{
    public:
        Folder(const string& s):folder_name(s){}
        Folder(const Folder&);
        Folder& operator=(const Folder&);
        ~Folder();
    
        void save(Message&);
        void remove(Message&);
    
        void addMsg(Message*);
        void remMsg(Message*);
    private:
        set<Message*> messages;
        string folder_name;
    
        void put_Fldr_in_Message(const set<Message*>&);
        void remove_Fldr_from_Message();
    };
    
    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; //actual message text
        set<Folder*> folders;//folders that have this message
        void put_Msg_in_Folder(const set<Folder*>&);
        void remove_Msg_from_Folders();
    };
    
    
    #endif // !MESSAGE_H
    #include "stdafx.h"
    #include "Message.h"
    
    
    Message::Message(const Message& m):contents(m.contents),folders(m.folders)
    {
        put_Msg_in_Folder(folders);
    }
    
    void Message::put_Msg_in_Folder(const set<Folder*>& rhs){
        for(set<Folder*>::const_iterator beg = rhs.begin();
            beg != rhs.end();++beg)
            (*beg)->addMsg(this);
    }
    Message& Message::operator=(const Message& rhs){
        if(&rhs != this){
            remove_Msg_from_Folders();
            contents = rhs.contents;
            folders = rhs.folders;
            put_Msg_in_Folder(rhs.folders);
        }
        return *this;
    }
    void Message::remove_Msg_from_Folders(){
        for(set<Folder*>::const_iterator beg = folders.begin();
                beg != folders.end();++beg)
                (*beg)->remMsg(this);
    }
    
    Message::~Message()
    {
        remove_Msg_from_Folders();
    }
    
    void Message::addFldr(Folder* f){
        folders.insert(f);
    }
    
    void Message::remFldr(Folder* f){
        folders.erase(f);
    }
    
    void Message::save(Folder& fldr){
        addFldr(&fldr);
        fldr.addMsg(this);
    }
    
    void Message::remove(Folder& fldr){
        remFldr(&fldr);
        fldr.remMsg(this);
    }
    
    //Folder
    Folder::Folder(const Folder& f):messages(f.messages),folder_name(f.folder_name){
        put_Fldr_in_Message(f.messages);
    }
    
    void Folder::put_Fldr_in_Message(const set<Message*>& rhs){
        for(set<Message*>::const_iterator beg = rhs.begin();
                beg != rhs.end(); ++beg)
                (*beg)->addFldr(this);
    }
    
    void Folder::remove_Fldr_from_Message(){
        for (set<Message*>::const_iterator beg =messages.begin();
             beg != messages.end(); ++beg)
             (*beg)->remFldr(this);
    }
    
    Folder& Folder::operator=(const Folder& rhs){
        if(&rhs != this){
            messages = rhs.messages;
            folder_name = rhs.folder_name;
            put_Fldr_in_Message(messages);
        }
        return *this;
    }
    
    Folder::~Folder(){
        remove_Fldr_from_Message();
    }
    
    void Folder::save(Message& msg){
        addMsg(&msg);
        msg.addFldr(this);
    }
    
    void Folder::remove(Message& msg){
        remMsg(&msg);
        msg.remFldr(this);
    }
    
    void Folder::addMsg(Message* msg){
        messages.insert(msg);
    }
    
    void Folder::remMsg(Message* msg){
        messages.erase(msg);
    }
  • 相关阅读:
    (转)大型分布式网站架构技术总结
    VC中怎么输入特殊符号(如平方、立方等下标符号)
    【转】VC++的Unicode编程
    【转】VC下的Unicode编程
    MFC多国语言——资源DLL
    MFC多国语言——资源副本
    【转】SetThreadLocale解决越南文乱码问题
    【转】msxml 操作xml
    关于形如--error LNK2005: xxx 已经在 msvcrtd.lib ( MSVCR90D.dll ) 中定义--的问题分析解决
    vc6项目-vc8项目 转换日志
  • 原文地址:https://www.cnblogs.com/jackStudy/p/4358486.html
Copyright © 2020-2023  润新知