条款18:让接口容易被正确使用,不易被误用

必须考虑客户可能做出什么样的错误(防御式编程)
std:shared_ptr会自动使用它的"每个指针专属的删除器",消除了"cross-DLL problem"(对象在DLL中被 new 创建,却在另一个DLL中 delete 销毁)

条款19:设计 class 犹如设计 type 类型系统

条款20:宁以 pass-by-reference-to-const 代替 pass-by-value

C语言永远是pass-by-value,C++默认是pass-by-value,函数参数都是以实际参数的副本拷贝为初值,函数调用的结果是函数返回值的一个副本拷贝
注意C语言中传指针方式,传指针具有引用语义,对象复制以后并没有分离,而是共享关联同一资源
采用pass-by-reference-to-const 效率高(无对象拷贝),是多态前提(基类引用),也可以避免基类和派生类之间的对象切割

条款21:必须返回局部对象时,禁止返回其reference

const Rational& operator*(const Rational& lhs, const Rational& rhs) {Rational result(lhs.n * rhs.n, lhs.d * rhs.d);return result;
}

这个函数返回一个reference指向result,但result是local对象,local对象在函数退出前已经被销毁了!!!

任何函数如果返回一个reference指向某个local对象都将一败涂地
任何函数如果返回一个指针指向某个local对象同样将一败涂地

const Rational& operator*(const Rational& lhs, const Rational& rhs) {static Rational result;result = ...;return result;
}

这个函数返回static对象,不具有多线程安全性,并行计算时极易出错

必须返回对象时,就让函数pass-by-value返回一个新对象

inline const Rational operator*(const Rational& lhs, const Rational& rhs) {Rational result(lhs.n * rhs.n, lhs.d * rhs.d);return result;
}

这个函数以pass-by-value方式返回值语义对象,值语义对象复制之后两者分离,所以函数结束后获得的仍然是正确的对象

总结:绝不要返回reference或pointer指向一个local对象

条款22:将成员变量声明为 private

客户唯一能够访问对象成员变量的方法就是通过存取函数get()和set()
成员变量的封装性与"成员变量的内容改变时所破坏的代码量"成反比

条款23:宁以non-member、non-friend 替换member函数(本人不认同)

条款24:操作符重载时必须选择设置为类成员还是普通的非成员函数

操作符重载时,选择成员还是非成员实现有一些指导原则:
1.赋值(=)、下标([])、调用( () )、成员访问(->)必须定义为类成员,否则编译出错
2.复合赋值操作符(+=)通常定义为类成员
3.对称操作符(算术运算符、关系运算符)通常选择为non-member函数实现
注:操作符选择类成员实现时,显式形参数比操作数数目少1,因为当操作符为成员函数时,this 指向左操作数

条款25:考虑写一个不抛异常的 swap 函数

STL提供的标准swap算法如下:

namespace std {template<typename T>void swap(T& a, T& b) {T temp(a);a = b;b = temp;}
}

缺省版本设计到对象复制,有时效率低下。但是考虑如下:

class WidgetImpl{
public:...
private:int a, b, c;std::vector<double> v;
};class Widget{
public:Widget(const Widget& rhs);Widget& operator=(const Widget& rhs) {...*pImpl = *(rhs.pImpl);}
private:WidgetImpl* pImpl;
};

一旦置换两个Widget对象,唯一需要做的就是置换其pImpl指针,可以考虑模板特化技术

namespace std{template<>void swap<Widget>(Widget& a, Widget& b) {swap(a.pImpl, b.pImpl); //目前还无法编译通过
    }
}

上述代码中 template<> 表示它是 std:swap的一个全特化版本,函数名之后的<Widget>表示这一特化版本只针对"T是Widget"而设计(偏特化)
上述代码不能通过编译,因为a.pImpl和b.pImpl都是 private,所以进行如下改进:

class Widget{
public:...void swap(Widget& other) {    //绝不可以抛出异常using std::swap;          //逼迫编译器使用std::swap(因为偏特化版本swap还未实现完成)swap(pImpl, other.pImpl); //此时使用的是std::swap
    }
}namespace std{template<>void swap<Widget>(Widget& a, Widget& b) {a.swap(b);}
}

一旦编译器看到对swap调用时,就会查找适当的swap调用,如果没有T专属之swap存在,编译器就会使用std内的swap

std::swap(obj1, obj2);    //错误的swap调用方式,强迫编译器总是调用std内部的swap版本
swap(obj1, obj2);         //正确的swap调用方式,不带任何的命名空间修饰

c++只允许对类模板进行偏特化,不能对函数模板进行偏特化

转载于:https://www.cnblogs.com/wwwjieo0/p/3443256.html

EC++学习笔记(四) 设计与声明相关推荐

  1. 华清远见fs4412开发板学习笔记(四)

    fs4412开发板学习笔记(四) 今天的课程安排 1.复习 1.1 VIM 编辑器 [1] vim + filename 打开 [2] 工作模式 命令模式 编辑模式 底行模式 [3] 模式切换 命令- ...

  2. 【http学习笔记四】安全篇

    [http学习笔记四]安全篇 文章目录 [http学习笔记四]安全篇 一.HTTPS 与 SSL/TLS ① 什么是安全? 机密性 完整性 身份认证 不可否认 ② 什么是HTTPS? ③ SSL/TL ...

  3. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  4. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  5. RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决)

    RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决) 参考文章: (1)RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决) (2)https://www.cnblogs. ...

  6. JSP学习笔记(四十九):抛弃POI,使用iText生成Word文档

    POI操作excel的确很优秀,操作word的功能却不敢令人恭维.我们可以利用iText生成rtf文档,扩展名使用doc即可. 使用iText生成rtf,除了iText的包外,还需要额外的一个支持rt ...

  7. Ethernet/IP 学习笔记四

    Ethernet/IP 学习笔记四 EtherNet/IP Quick Start for Vendors Handbook (PUB213R0): https://www.odva.org/Port ...

  8. OpenCV学习笔记四-image的一些整体操作

    title: OpenCV学习笔记四-image的一些整体操作 categories: 编程 date: 2019-08-08 12:50:47 tags: OpenCV image的一些操作 sP4 ...

  9. 吴恩达《机器学习》学习笔记四——单变量线性回归(梯度下降法)代码

    吴恩达<机器学习>学习笔记四--单变量线性回归(梯度下降法)代码 一.问题介绍 二.解决过程及代码讲解 三.函数解释 1. pandas.read_csv()函数 2. DataFrame ...

最新文章

  1. python解包裹_关于Python中包裹传参和解包裹的理解
  2. Xpath语法-爬虫(一)
  3. redis主从集群搭建eclipse_【Redis】Redis 主从模式搭建
  4. day、11闭包函数和装饰器
  5. pyplot设置刻度字体大小以及标签字体大小
  6. 100_1小记ressons analysis
  7. spring 事务的传播行为详解(转)
  8. 深入解读Linux内存管理系列(4)——Memblock管理机制
  9. 电力电子仿真-plecs3.6.1安装包
  10. 树莓派管脚编码c语言,树莓派IO引脚定义 | 北岛夜话
  11. 什么是网络爬虫?爬虫有什么好处?
  12. 《C++程序设计上机实践及学习辅导》实验报告
  13. fx3u4ad一adp说明书_三菱FX3U-4AD-ADP用户手册FX3U-4AD-ADP模拟控制版本手册 - 广州凌控...
  14. 铝巨人铝模软件_助力建筑工业化发展PKPM-LMB铝模设计软件正式发布
  15. android执行lua脚本的方法,android执行lua脚本的方法
  16. 时间戳与日期相互转换
  17. 12月26日学习记录
  18. ppc64le处理器国产power8服务器CentOS7.2安装ibm-jdk
  19. C语言 | 将字符串中的元音字母复制到另一个字符串中
  20. 迪米特法则——面向对象设计原则

热门文章

  1. SpringBoot接收数组参数
  2. idea 高级调试技巧
  3. springMVC中获取request 对象
  4. C语言 main函数参数 argc,argv 用处,控制台应用程序模板2
  5. 攻防世界 WEB 新手练习区 答题(1-12题解)
  6. java 集合排序方法_java集合排序方法sort的使用
  7. asp获取计算机mac,ASP获取客户端MAC地址(源代码)
  8. java的字符_Java中的字符
  9. Lc695-岛屿的最大面积
  10. Python源码深度解析—Python提供的C API