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);
}
C++primer 阅读点滴记录(一)的更多相关文章
- C++primer 阅读点滴记录(三)
14章 操作符重载和转换 重载操作符是具有特殊名称的函数:保留字operator后接需要定义的操作符符号. 1.重载的操作符名: + – * / % ^ & | ~ ! , = < & ...
- C++primer 阅读点滴记录(二)
智能指针(smart point) 除了增加功能外,其行为像普通指针一样. 一般通过使用计数(use count)或引用计数(reference count)实现智能指针,防止出现指针 ...
- C++ Primer 阅读笔记:迭代器和容器 小结
原创 by zoe.zhang 0.写在前面的话 我是在2011年学的C++,但是那一年恰好是C++11新标准的一年,但是大学上学的C++还是基于C++98的风格的,使用的编译器也是VC6.0,啊, ...
- 《JavaScript高级程序设计(第3版)》阅读总结记录第一章之JavaScript简介
前言: 为什么会想到把<JavaScript 高级程序设计(第 3 版)>总结记录呢,之前写过一篇博客,研究的轮播效果,后来又去看了<JavaScript 高级程序设计(第3版)&g ...
- [踏得网]HTML5在线教程阅读进度记录
2017年1月3日18:12:19http://techbrood.com/h5b2a?p=html-canvas-states 2017年1月3日17:10:11http://techbrood.c ...
- android 点滴记录 ICCID IMSI IMEI MEID 关系 和 区别,相关参数在什么情况下可以获取...
1:ICCID:Integrate circuit card identity 集成电路卡识别码(固化在手机SIM卡中) ICCID为IC卡的唯一识别号码,共有20位数字组成,其编码格式为:XXXXX ...
- android 点滴记录
1.AndroidM环境下,在framework层添加代码会对jar包的package name进行检查,并提示”unknown package name of class file”怎么解决? 产生 ...
- MiniProfiler使用点滴记录-2017年6月23日11:08:23
1.看似针对同样一段查询表ef达式,重复执行却没有被记录下来.其实这是正常情况,因为ef并没有重复去执行 相同sql查询. 2.MiniProfiler结合MVC过滤器进行 拦截记录Sql,示例代码: ...
- Git点滴记录
合并多个commit记录 假设我们当前有三个commit信息,现在要将commit hash为 23f92c 和 409978 合并 //git rebase -i HEAD~3 那么我们可以使用 r ...
随机推荐
- cctype函数 (字符类型判断)
这些函数都在cctype头文件定义 isalnum(c) 如果C是字母或数字,则为TRUE isalpha(c) 如果C是字母,返回TRUE iscntrl(c) 如果C是控制字符,返回TRUE ...
- 在点击HOME键时, 在点击icon回到原来的应用。
参考资料: http://www.linuxidc.com/Linux/2012-01/51332.htm
- elasticsearch从mysql导入数据
详细:https://github.com/jprante/elasticsearch-jdbc(最下面有各数据库的导入方法说明) elasticsearch版本为1.5.2 1.下载 elastic ...
- springMVC之HelloWorld
一.总结 1.web项目一定要把引用的jar包放在WEB-INF/lib下(common-logging1.2,spring4.1.6所有包,其实不需要那么多,懒得筛选了,) 2.web.xml中要初 ...
- JQuery上传插件uploadify整理(Events)
Arguments fileThe file object being cancelled onCancel:调用calcel方法.$('#upload').uploadify('cancel'); ...
- & replace &
var decoded = encoded.replace(/&/g,'&'); http://stackoverflow.com/questions/3700326/decode-a ...
- 动手学servlet(四) cookie和session
Cookie cookie是保存在客户端的一个“键值对”,用来存储用户的一些信息 cookie的应用: -在电子商务会话中标识用户 -对网站进行定制,比如你经常浏览哪些内容,就展示哪些页面给你 - ...
- js面向过程改写成面向对象--通用方法
响亮的标题:一个万能的,保底的.面向过程改写成面向对象的方法 前提朗读:很多刚接触js面向对象的时候都不知道如何能快速的写出一个面向对象的程序,这个是必然的现象,不是每一位学js的一上来就会写面向对象 ...
- sc delete 服务器名提示“指定的服务已经标记为删除”
症状:停止服务后,右键无法点击“启动”,打开命令输入SC删除服务后提示如标题描述 原因:进程还在 解决方案:打开任务管理器,进程,找到你的已停止服务名,右键,结束进程,再操作即可删除服务
- Error querying database. Cause: java.sql.SQLException: ORA-01745: 无效的主机/绑定变量名
今天调试程序是遇到了,下面的一个问题.我将对应的SQL语句拿到Toad下也能正常的执行,感觉有点莫名其妙,根据异常信息的提示查看对应的映射结果集也没发现错误,然后百度了一下,也有许多朋友也遇到过这样的 ...