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

设计接口的原则:正确性、高效性、封装性、维护性、延展性以及协议的一致性;

设计原则:1)导入新类型来预防很多客户端的错误,多使用系统类型(type system(划分为多个explicit函数),如果某个变量的可选情况有限,可以通过static函数来替代对象,表示某个特定的对象,并将对象的构造函数定义成private来防止新的对象生成,具体代码如下:

class  month{

public:

static month Jan( ) {return month(1);}//以函数替代对象,来代替某个特定的月份

...

private:

explicit month(int m);

};

date(month::Jan( ));//调用

2)限制类型内,什么事情可以做,什么事情不可以做,通常加上限制const;

3)让你的types的行为和内置types行为一致,提供行为一致的接口;

4)使用智能指针来管理系统资源,可以避免内存泄露(注意智能指针的管理方式和管理条件(单个对象),并用自定义的deleter(资源释放函数)绑定在智能指针上,deteler(可缺省)),代码如下:

std::tr1::shared_ptr<investment>pinv(static_cast<investment*>(0),getridofinvestment);

//shared_ptr第一个参数必须要求是一个指针,一个空指针shared_ptr

//getridofinvestment为删除器

这样的初始化不是最优的:先把pinv初始化为nullptr后对其进行赋值操作(相当于初始化过程是多余的,如果知道初始指针的话,直接用初始指针来初始化pinv才是最优的);

使用智能指针的另外一个好的特性,它会自动使用它的各一个指针专属的删除器,因而消除一个潜在的客户错误(cross-DLL problem),即;对象在动态连接程序库(DLL)中被new创建,却在另外一个DLL内被delete,这一类称为“跨DLL之new/delete成对运用”会导致运行期错误,但是智能指针没有这个问题,它缺省的删除器来自于智能指针诞生的那个delete;

Boost的shared_ptr指针是原始指针(raw pointer)的两倍大,以动态分配内存作为簿记用途和“删除器之专属数据”,以vrtual形式调用删除器,并以多线程程序修改引用次数时承受线程同步化的额外开销,但这些额外的执行成本并不显著,但是在降低客户错误的方面却起到了很好的效果;

条款19:设计class犹如设计type

在设计一个新的class的时候,就像设计一个新的type,在设计一个高效的class的时候,应该考虑的问题有:

1)对象如何被创建和销毁;

2)对象初始化和赋值之间有什么差别;

3)新对象在传值和传引用方面的考虑;

4)对于成员变量引申的成员函数需要进行的错误检查工作及函数抛出异常及异常处理;

5)考虑类型的继承和被继承情况;

6)类型需要做什么样的转换,编写对应的类型转换函数;

7)什么函数应该是成员函数,什么不是;

8)什么函数应该定义为private;9)成员变量的属性;

9)保证效率、异常安全性以及资源利用(多任务锁定和动态内存);

10)一般化你的类型,考虑定义一个模板类;

11)是否需要定义类,可以在别人类的基础上添加一个或者多个non-member函数或者template;

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

缺省情况下C++以by-value方式传递对象到函数,函数参数都是以实际实参的副本为初值,而调用端所获得的也是函数返回值的一个附件,这些副本由对象的copy构造函数产生,使得pass-by-value称为一个函数操作,如果有很多成员变量的时候;

如果采用传递引用的方式,没有任何的构造函数或者析构函数调用,因为没有任何的对象被创建;除此之外,以传引用的方式传递参数可以避免slicing(对象切割)的问题,即当一个对derived class对象以by value的方式传递并视为一个base class对象,base class的拷贝构造函数被调用,但是derived class区别于base class的部分会被切割掉,而只留下一个base class;

避免是slicing(切割)问题的方法,就是采用by-reference-to-const的方式传递,原因是因为reference往往是以指针的形式实现,pass by reference通常意味着传递的是指针;

一般而言,对于内置类型、STL的迭代器和函数对象,采用传值比较方便,其他最好使用传引用;

条款21:必须返回对象时,别妄想返回其reference

对于reference只是一个名称,代表某个既有对象。任何时候看到一个reference声明式,应该去了解它的另外一个名称是什么?

分析代码如下:

//返回引用指向栈上的变量

错误方法1.const rational& operator*(const rational&lhs,const rational &rhs){

rational result(lhs.n*rhs.n,rhs.d*rhs.d);//试图返回一个栈空间变量为引用

return result;                                   //对象在函数调用结束后被销毁,引用指向一个错误的对象;

}

//返回引用指向堆上的变量

错误方法2.const rational& operator*(const rational&lhs,const rational &rhs){

rational *result=new rational(lhs.n*rhs.n,rhs.d*rhs.d);//如何对这个new内存进行管理

return *result;             //没办法取得reference背后的指针,如何a*b*c时更容易出错;

}

//返回引用指向一个函数内部的static rational对象

错误方法3.const rational& operator*(const rational&lhs,const rational &rhs){

static rational result;    //staitc对象会导致多线程安全性

result=rational temp(lhs.n*rhs.n,rhs.d*rhs.d);//static公用问题会带来错误的影响;

return result;

}

rational a,b,c,d; if(a*b==c*d)//if里面的数据一直为真,不管其他的怎么取值,因为static原因和返回是引用的原因

正确代码:inline const rational operator*(const rational&lhs,const rational &rhs){

rational result(lhs.n*rhs.n,rhs.d*rhs.d);//虽然会有拷贝构造和析构的成本,但是对于安全性考虑却是一个很好的做法;

}

结论:不要返回pointer或者reference指向一个local stack对象(见错误方法1),或返回一个reference指向一个heap-allocated对象9见错误方法2),或返回pointer或reference指向一个local static对象而有可能同时需要多个这样的对象(见错误方法3)

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

如果成员变量不是public,客户能够访问对象的方式就是通过成员变量函数,如果public接口内的每样东西都是函数,那么可以避免客户在调用class成员时考虑是否需要使用小括号;如果你通过函数访问成员变量,那么你以后你改变成员变量时,class客户却完全不知道class 内部发生了变化;

将成员变量隐藏在函数接口的背后没可以为“所有可能的实现”提供弹性;你对客户隐藏成员变量(封装性),你可以确定class的约束条件得到维护,因为只有成员函数可以影响它们;

某个东西的封装性与“当其内容改变时可能造成的代码破坏量”成反比,改变就是从class中移除它;

一旦你声明成员变量为public或者protected时,就很难改变这个成员变量涉及的一切,有太多的代码需要重写、重新测试、重新编写、重新编译;

结论:将成员变量声明为private,这可以赋予客户访问数据的一致性、可细微划分访问控制、允诺约束条件获得保证,并为class提供充分的实现弹性;

Effective C++学习第六天相关推荐

  1. Vue 学习 第六天学习笔记

    Vue 学习 第六天学习笔记 1.webpack  使用复习 第一步:先建立文件夹. 第二步,用webpack将其初始化,建立管理.npm 的包管理工具管理起来, npm init -y  .注意{查 ...

  2. python count函数用法 comm_Python学习第六天课后练习案例 (主要针对的内容是python函数的定义和使用)...

    Python学习第六天课后练习案例 2019.07.19 1.定义一个函数,该函数可以实现在内部输入一个信息,如果该信息不能转换为正整数,则重新输入,直到能转换为正整数,则对外返回转换的正整数 程序代 ...

  3. Effective C++ 学习笔记 第七章:模板与泛型编程

    第一章见 Effective C++ 学习笔记 第一章:让自己习惯 C++ 第二章见 Effective C++ 学习笔记 第二章:构造.析构.赋值运算 第三章见 Effective C++ 学习笔记 ...

  4. Python学习.第六天.字典

    Python学习.第六天.字典 前言 一.什么是字典? 二.字典的原理 三.字典的创建与删除 四.字典的查询操作 五.字典元素的增.删.改操作 1.key的判断: 2.字典元素的删除 3.字典元素的新 ...

  5. effective c++ 学习

    <Effective C++> 目录: 转自:http://blog.csdn.net/KangRoger/article/details/44706403 目录 条款1:视C++为一个语 ...

  6. 51单片机入门学习 第六天

    提示:今天是学习51单片机的第六天,以下就是今天的笔记(我买的是普中的开发板,学习笔记是根据普中的视频进行学习) 目录 独立按键实验 1.按键介绍 2.硬件设计 3.软件设计 矩阵按键实验 1.矩阵按 ...

  7. Effective C++学习第十一天

    条款41:了解隐式接口和编译期多态 面向对象编程世界总是以显式接口(源码可见的接口)和运行期多态(virtual)解决问题:对于templates及泛型编程的世界,隐式接口和编译期多态显得更加重要: ...

  8. C#学习第六天 基础语法练习游戏--飞行棋

    前几天学习的实践:游戏---飞行棋 步骤: 1.画游戏头 2.初始化地图(加载地图所需要的资源) 将整个数组中的数字变成控制台中显示的特殊字符串的过程,就是初始化地图 int[100]代表100个符号 ...

  9. More effective C++学习总结

    More effective C++摘要 3 基础议题部分: 3.1 M1:指针与引用的区别 首先,要认识到在任何情况下都不能使用指向空值的引用,引用必须被初始化.一个引用必须总是指向某些对象. (不 ...

最新文章

  1. 红帽虚拟化RHEV-安装RHEV-M
  2. [YTU ]_2736指针练习--输出最大值
  3. 在ubuntu怎样修改默认的编码格式
  4. Map集合根据key,value排序
  5. 单目摄像头光学图像测距_自动驾驶汽车传感器技术解析——车载摄像头
  6. Android 基本开发规范(必读)
  7. SAP License:SAP创建中国版免费在线公开课程openSAP
  8. 红帽干掉 CentOS 8,CentOS Stream 上位
  9. 网络协议:关于TCP/IP,必须知道的十个知识点
  10. react进行状态管理的几种方式
  11. 使用Vitamio开发iOS平台上的万能播放器
  12. 伺服电机(舵机)简单介绍
  13. ipad 在线打代码 code-server
  14. 计算机自动维护有用吗,Win10怎么开启自动维护功能?系统自动维护有什么作用?...
  15. Ninja ripper 工具使用教程
  16. 大数据工程师四能力你拥有几种?
  17. Programming Assignment 4: Boggle
  18. hyperf使用curl产生的超时问题
  19. 微信支付平台设置及如何获取微信支付所需参数
  20. ArcGIS提取斜坡单元

热门文章

  1. 阅读react-redux源码(四) - connectAdvanced、wrapWithConnect、ConnectFunction和checkForUpdates
  2. Spring @Value取值为null或@Autowired注入失败
  3. JAVA运算符和优先级
  4. Linux中exit与_exit的区别
  5. c++ 请抛弃匈牙利命名法 - 变量命名代码风格的建议。
  6. sqlserver 数据库日志文件过大的问题
  7. python知识点汇总_Python知识点总结大全(一)
  8. 电脑入门完全自学手册_3DMAX零基础入门到精通的学习路线和教程
  9. java显示长度和第一个字符_从Java字符串中以长度1的字符串返回的第一个字母的最佳方法是什么?...
  10. pdo 参数化查询 mysql函数_PDO笔记之参数化查询