第十三章 复制控制:(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);
}

C++primer 阅读点滴记录(一)的更多相关文章

  1. C++primer 阅读点滴记录(三)

    14章 操作符重载和转换 重载操作符是具有特殊名称的函数:保留字operator后接需要定义的操作符符号. 1.重载的操作符名: + – * / % ^ & | ~ ! , = <  & ...

  2. C++primer 阅读点滴记录(二)

      智能指针(smart point)       除了增加功能外,其行为像普通指针一样. 一般通过使用计数(use count)或引用计数(reference count)实现智能指针,防止出现指针 ...

  3. C++ Primer 阅读笔记:迭代器和容器 小结

    原创 by zoe.zhang  0.写在前面的话 我是在2011年学的C++,但是那一年恰好是C++11新标准的一年,但是大学上学的C++还是基于C++98的风格的,使用的编译器也是VC6.0,啊, ...

  4. 《JavaScript高级程序设计(第3版)》阅读总结记录第一章之JavaScript简介

    前言: 为什么会想到把<JavaScript 高级程序设计(第 3 版)>总结记录呢,之前写过一篇博客,研究的轮播效果,后来又去看了<JavaScript 高级程序设计(第3版)&g ...

  5. [踏得网]HTML5在线教程阅读进度记录

    2017年1月3日18:12:19http://techbrood.com/h5b2a?p=html-canvas-states 2017年1月3日17:10:11http://techbrood.c ...

  6. android 点滴记录 ICCID IMSI IMEI MEID 关系 和 区别,相关参数在什么情况下可以获取...

    1:ICCID:Integrate circuit card identity 集成电路卡识别码(固化在手机SIM卡中) ICCID为IC卡的唯一识别号码,共有20位数字组成,其编码格式为:XXXXX ...

  7. android 点滴记录

    1.AndroidM环境下,在framework层添加代码会对jar包的package name进行检查,并提示”unknown package name of class file”怎么解决? 产生 ...

  8. MiniProfiler使用点滴记录-2017年6月23日11:08:23

    1.看似针对同样一段查询表ef达式,重复执行却没有被记录下来.其实这是正常情况,因为ef并没有重复去执行 相同sql查询. 2.MiniProfiler结合MVC过滤器进行 拦截记录Sql,示例代码: ...

  9. Git点滴记录

    合并多个commit记录 假设我们当前有三个commit信息,现在要将commit hash为 23f92c 和 409978 合并 //git rebase -i HEAD~3 那么我们可以使用 r ...

随机推荐

  1. cocos2d-x 游戏暂停界面,监听home键,返回键,Menu键 解决方案

    游戏暂停界面: cocos2d-x中游戏暂停界面提供的思路是用pushScene()和popScne(),即推进和弹出场景,当游戏暂停时,推进(pushScene())暂停场景,之前运行的场景将会自动 ...

  2. MapReduce从输入文件到Mapper处理之间的过程

    1.MapReduce代码入口 FileInputFormat.setInputPaths(job, new Path(input)); //设置MapReduce输入格式 job.waitForCo ...

  3. Redis附加功能之Redis流水线pipeline

    流水线功能的目的:通过减少客户端与服务器之间的通信次数来提高程序的执行效率. 一.通信 在一般情况下, 用户每执行一个 Redis 命令,客户端与服务器都需要进行一次通信:客户端会将命令请求发送给服务 ...

  4. cocos2d-x 中添加显示文字的三种方式 LabelTTF 、LabelBMFont 和 LabelAtlas

    在 cocos2d-x 中有三个类可以在层或精灵中添加文字: LabelTTF LabelBMFont LabelAtlas LabelTTF 直接支持使用 TTF 字库,可以支持全部的中文,但是效率 ...

  5. Botposter.com集群ETCD2.3.7升级至3.0实录[原创]

    7月1日,为庆祝我党生日,ETCD隆重发布了3.0版本.Botposter.com也在第一时间对集群进行了升级.本文是升级过程的记录与总结(文中假设读者已经使用或测试过ETCD V2,如有不妥请见谅) ...

  6. 设计模式——适配器模式(Adapter Pattern)

    解决的问题: 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作.比如说我的hp笔记本,美国产品,人家美国的电压是110V的,而我们中国 ...

  7. 操作系统是怎么工作的——mykernel环境的搭建

    可以参见:https://github.com/mengning/mykernel 首先感谢:http://www.euryugasaki.com/archives/1014 1.搭建实验环境(实验环 ...

  8. dreamweaver cs6 的破解方法

    dreamweaver cs6 的破解方法,很简单大家照着下面的方法做肯定能破解方法/步骤 安装DreamWeaver cs6 使用amtlib.dll破解下载amtlib.dll文件后,解压后得到 ...

  9. Find out who the “mole” is?

    Blueheat Company’s  production server was out of order again. The CEO was very upset and want their ...

  10. ntfs安全权限和共享权限的区别

    win xp 最大分区32G,最大文件大小4G. 共享权限是为网络用户设置的,NTFS权限是对文件夹设置的. 用户对文件夹有什么权限就是看NTFS权限的设置. 如果一个文件夹设置成共享,其具体的权限还 ...