Item18:让接口容易被正确使用,不易被误用

总结:

1.好的接口很容易被正确使用,不容易被误用。你应该在你的所有接口中努力达到这些性质。

2.“促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容。

3.“阻止误用”的办法包括建立起新类型、限制类型上的操作,束缚对象的值,以及消除客户的资源管理责任。

4.trl::shared_ptr支持定制型删除器(custon destructor)。这可以防范DLL问题,可以被用来自动解除互斥锁(mutexes)


Item19:设计class犹如设计type

如何设计一个高效的class?首先你必须了解你将面临的一些问题:

1.新的type的对象应该如何被创建和销毁?这会影响到你的class构造函数和析构函数以及内存分配函数和释放函数(operator new,operator new[],operator delete,operator delete[]})。

2.对象的初始化和对象的赋值该有怎么样的差别?这个答案决定了你的构造函数和赋值(assignment)操作符的行为,以及中间的差异。很重要的是别混淆了“初始化”和“赋值”,因为它们对应了不同的函数调用。

3.新的type的对象如果被passed by value,意味着什么?记住,copy构造函数用来定义一个type的pass-by-value该如何实现。

4.什么是新type的“合法值”?对于class的成员变量而言,通常只有某些数值集是有效的,那些数值决定了你的class必须维护的约束条件,也就决定了你的成员函数(特别是构造函数、赋值操作、和所谓的“setter函数”)必须进行的错误检查工作。

5.你的type需要配合某个继承图系吗?如果继承自某些已经有的classes,那么该type就会受到那些classes的设计的束缚,特别是受到它们的函数是virtual或者是non-virtual的(尤其是析构函数)。

6.你的新type需要类型转换吗

7.什么样的操作符和函数对此type是合理的?这个问题的答案将决定你将为你的class声明什么member函数。

8.什么样的标准函数应该禁止被使用?那些正是你要设置为private的函数。

9.谁该取用新的type成员?这个提问将帮助你决定哪个成员是public,那个是private或者protected。它也帮助你决定哪一个class或function是friend。

10.什么是新type的“未声明接口”?它对效率、异常安全性以及资源运用提供何种保证?在这方面提供的保证将为你的class实现代码加上约束条件。

11.你的新type有多么一般化?或许你定义的并非是一个新的type,而是一整个type家族,那么你将需要使用template。

12.你真的需要一个新的type吗?如果只是定义新的derived class以便为现有的class添加机能,那么说不定单纯定义一个或者多个non-member函数或者tmeplates,更加能够达到目标。

总结:请记住,class的设计就是type的设计,在定义一个新的type之前,请确定你已经考虑过本条提议所覆盖的主题。


Item20:宁以pass-by-reference-to-const替换pass-by-value

以pass-by-reference方式传递参数可以避免slicing(对象切割问题)。当一个derived 对象以by-value的方式作为参数传递的时候,会被认为是一个base class对象,base class的copy构造函数会被调用,而“造成此对象的行为像个derived class 对象”的那些特化性质全都被切割掉了,仅仅剩下了一个base class对象。

void show(father a)//以值传递
{
//do something...
}
int main()
{
son s;
show(s);//如果你用子类的对象传进来的话,会被构造出一个父类对象,而子类对象的那些特性全都被“切割”掉了!!!
}

当然,如果你的参数是一个内置类型的话,用pass-by-value的方式往往比pass-by-reference的效率要高(引用的底层还是使用指针来实现的)。

总结:

  • 尽量以pass-by-reference-to-const替换pass-by-value。前者通常比较高效,并且可以避免切割问题(slicing problem)。
  • 以上规则并不适合内置类型,以及STL的迭代器和函数对象。对它们而言,pass-by-value往往比较恰当。

Item21:必须返回对象时,别妄想返回其reference

总结:

  • 绝对不要返回一个reference或者pointer指向一个local stack对象,或者返回一个reference指向一个heap-allocated对象,或者返回pointer或reference指向一个local static对象而有可能同时需要多个这样的对象。条款4已经为“在单线程环境下合理返回reference指向一个local static对象”提供了一种解决方案。
  • -


Item22:将成员变量声明为private

总结:

  • 切记将成员变量声明为private。这可以赋予客户访问数据的一致性、可细微划分访问控制、允许约束条件获得保证,并提供class作者以充分的实现弹性。
  • protected并不比public更具有封装性。(如果想更详细的了解,可以参阅书本)

Item23:宁以non-member、non-friend替换member函数

总结:

  • 宁可拿non-member、non-friend替换member函数。这样做可以增加封装性、包裹弹性(packaging flexibility)和机能扩充性。
  • -


Item24:若所有参数皆需参数类型转换,请为此采用non-member函数

总结:

  • 如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻的参数)进行类型转换,那么这个函数必须是个non-member。

Item25:考虑写一个不抛出异常的swap函数

总结:

  • 当std::swap对你的类型效率不高的时候,提供一个swap函数,并确定这个函数不会抛出异常。
  • 如果你提供一个member swap,也应该提供一个non-member swap函数用来调用前者。对于classes(而非templates),也请特化std::swap。
  • 调用swap时应针对std::swap使用using声明式,然后调用swap并不带任何“命名空间资格修饰”。
  • 为“用户定义类型”进行std templates全特化是好的,但千万不要尝试在std内加入对std而言全新的东西。

《Effective C++》设计与声明章节的更多相关文章

  1. Effective C++ ——设计与声明

    条款18:让接口更容易的被使用,不易误用 接口设计主要是给应用接口的人使用的,他们可能不是接口的设计者,这样作为接口的设计者就要对接口的定义更加易懂,让使用者不宜发生误用,例如对于一个时间类: cla ...

  2. Effective C++ —— 设计与声明(四)

    条款18 : 让接口容易被正确使用,不易被误用 欲开发一个“容易被正确使用,不容易被误用”的接口,首先必须考虑客户可能做出什么样的错误操作.  1. 明智而审慎地导入新类型对预防“接口被误用”有神奇疗 ...

  3. 《Effective C++》第4章 设计与声明(2)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  4. 《Effective C++》第4章 设计与声明(1)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  5. 《Effective C++》阅读总结(四): 设计、声明与实现

    第四章: 设计与声明 18. 让接口更容易被正确使用,不易被误用 将你的class的public接口设计的符合class所扮演的角色,必要时不仅对传参类型限制,还对传参的值域进一步限制. 19. 设计 ...

  6. EffectiveC++ 第4章 设计与声明

    我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter4 设计与声明 Designs and Declarat ...

  7. Effective C++笔记:设计与声明

    条款18:让接口容易被正确使用,不易被误用 1,好的接口很容易被正确使用,不容易被误用.你应该在你的所有接口中努力达成这些性质. 2,“促进正使用”的办法包括接口的一致性,以及与内置类型的行为兼容. ...

  8. Effective C++笔记04:设计与声明

    条款18:让接口easy被正确使用,不易被误用 1,好的接口非常easy被正确使用,不easy被误用.你应该在你的全部接口中努力达成这些性质. 2,"促进正使用"的办法包含接口的一 ...

  9. 《Effective C++》设计与声明:条款18-条款25

    条款18:让接口容易被正确使用,不容易被误用 注意使用const,explicit,shared_ptr等来限制接口. 必要时可以创建一些新的类型,限制类型操作,束缚对象等. 注意保持接口的一致性,且 ...

  10. Effective C++笔记(四):设计与声明

    参考:http://www.cnblogs.com/ronny/p/3747186.html 条款18:让接口容易被正确使用,不易被误用 1,好的接口很容易被正确使用,不容易被误用.你应该在你的所有接 ...

随机推荐

  1. LcdTools如何添加图片画面到PX01显示

    LcdTools打开点屏工程,切到"画面设置"栏,在"画面资源"栏选择"Picture"画面,先设置图片ID编号(此编号用于PG对图片编号, ...

  2. 2.Python封装练习及私有属性

    面向对象三大特性 封装:根据职责将属性和方法封装到一个抽象的类中 继承:实现代码的重用,相同代码不需要重复的编写 1.单继承 2.多继承 多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的 ...

  3. Sublime Text - Linux Package Manager Repositories

    Linux Package Manager Repositories http://www.sublimetext.com/docs/linux_repositories.html Sublime T ...

  4. 云小课|MRS基础原理之MapReduce介绍

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:MapReduce ...

  5. 所有selenium相关的库

    通过爬虫 获取 官方文档库 如果想获取 相应的库 修改对应配置即可 代码如下 from urllib.parse import urljoin import requests from lxml im ...

  6. 基于案例分析 MySQL Group Replication 的故障检测流程

    故障检测(Failure Detection)是 Group Replication 的一个核心功能模块,通过它可以及时识别集群中的故障节点,并将故障节点从集群中剔除掉.如果不将故障节点及时剔除的话, ...

  7. [数据结构-线性表1.2] 链表与 LinkedList<T>(.NET 源码学习)

    [数据结构-线性表1.2] 链表与 LinkedList<T> [注:本篇文章源码内容较少,分析度较浅,请酌情选择阅读] 关键词:链表(数据结构)    C#中的链表(源码)    可空类 ...

  8. (译)TDD(测试驱动开发)的5个步骤

    原文:5 steps of test-driven development https://developer.ibm.com/articles/5-steps-of-test-driven-deve ...

  9. networkQuality

    基本使用 networkQuality 是一个命令行工具,需要使用「终端」App(或者你首选的其他终端模拟器)运行.方法是: 首先,点按「程序坞」(Dock)中的「启动台」(LaunchPad)图标, ...

  10. Go语言核心36讲46

    我们今天要讲的是os代码包中的API.这个代码包可以让我们拥有操控计算机操作系统的能力. 前导内容:os包中的API 这个代码包提供的都是平台不相关的API.那么说,什么叫平台不相关的API呢? 它的 ...