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);
}
posted @ 2015-03-23 23:40  hongjack  阅读(219)  评论(0编辑  收藏  举报