c++编程惯用法
----高级程序员常用方法和技巧
第1章 抽象
- 设计抽象模型和设计实现细节应该是两个相互独立且相关的行为。
- 没有出现在抽象模型中的东西和出现在其中的东西一样重要
- 如果存在疑问,先不要考虑它。添加新的功能通常都不会有兼容性的问题,但是去除一个已有的功能则可能导致代码失效。
- 彻底的检测和记录下设计中的关键点。
- 设计是一个迭代的过程。
- 请考虑边界条件。
- 在设计初始阶段使用CRC卡片。
- 判断缺省的复制构造函数和赋值操作符的行为是否符合我们的期望,必要时重新实现它们。
- 避免使用赋值操作来初始化成员,使用构造函数初始化语法来完成初始化操作。
- 当编写赋值操作符时,请检测s = s 这种情况。
- 避免出现公用数据。
- 尽可能少的声明和使用隐式类型转换。避免在同一个类中出现两个(或者多个)转换操作符。
- 一元操作符,赋值操作符,(), [] ,以及 -> 应该被定义为成员函数,其它操作符应该被定义为非成员函数。
- 使用缺省值来为同一个函数提供不同的调用方式,使用函数重载来为同一个抽象操作提供多种实现。
- 除非被调用函数需要它自己的对象拷贝,否则请使用传递常量引用的方式来调用函数。
- 在可能的情况下,将指针参数声明为指向常量的指针,将引用参数声明指向常量的引用。
- 在可能的情况下,将成员函数声明为const。
- 不同文件中的静态数据的初始化顺序没有被明确的定义。
- 使用句柄来用常量大小的对象表示不确定大小的值
- rep类要么是一个嵌套类,要么是一个所有成员都为私有,但是“真正”的类是它的友类。
- 使用计数器可以避免额外的复制操作,但是我们还是需要对性能进行检测以确信使用它可以带来性能上的提高。
- 句柄可用来确保对实现(而不是接口)的改变只会要求用户进行重新连接而不是重新编译。它们同样可以对他人隐藏实现的细节。
- 句柄可以允许构造函数基于参数从一系列的实现中挑选合适的实现。
- 句柄不一定是一个普通指针,它们也可以是“智能指针”的对象。
- 继承描述的是is-a 关系,派生类所实现的对象应该是基类所实现对象集中的一个子集。
- 当继承是接口的一部分时,请使用公有继承。只有当继承被用来隐藏实现的细节时,我们才需要使用私有和保护类型继承。
- 对于私有继承的大部分使用,我们都可以用组合来替代;只有当派生类需要重写(私有)基类中的虚函数时,我们才不能那样做。
- 在派生类中被重写的虚函数应该和基类中的抽象模型相一致。
- 构造函数,析构函数,以及赋值操作符不能够被继承。
- 只有派生类中包含多个基类,并且这多个基类间没有继承关系时,我们才可以使用多重继承。
- 使用虚基类来避免在同一个对象中出现多份基类子对象。
- 基类对象的构造顺序和它们在类声明中(而不是在构造函数的定义中)的顺序一样。
- 为每个基类明确的指定存取类型。
- 每个类都向外给出两个接口:一个面向用户,一个面向派生类。
- 对于一个会被用来作为基类的类来说,我们应该同时设计和记录下这两个接口(以及和它们相对应的抽象模型)。
- 为继承所进行的设计会带来运行时的性能消耗。并使得抽象模型更加复杂。对于某些类来说,它可能很有用,但对于其他类来说并非如此。
- 在所有被用来继承的类都应该有一个虚析构函数。
- 虚基类是在最外层的派生类中被初始化的。
- 避免使用保护类型数据。
- 将小的,经常被调用的函数声明为虚函数会导致程序的运行速度显著变慢。
- 对于中等和大规模的成员函数来说,将他们声明为虚函数时候不用犹豫------------这样做并不会给性能带来显著变化。
- 使用基类来提供影响到整个对象的服务。
- 当用于处理对象的逻辑和对象本事无关的时候,我们最好使用模版。
- 模版实例间的关系必须明确地用程序注明。
- 当模版类同时也是模版参数时,请在两个 > 间加入空格以避免语法错误,如 List< Set<int> >而不是 List< Set<int>>。
- 模版的实例化细节和我们具体使用编译器有关。
- 通过提供operator T* 和(对于指向自定义类型对象的指针来说)operator-> ,我们就可以实现智能指针模版。
- 在模版中使用表达式作为参数会使使用模版的难度变大,但对于极度关注性能的类来说,这种不便是值得的。
- 尽量减少模版函数的规模。
第8章 模版的高级用法
- 用模版实现的容器应该是同型的。我们可以提供使用一个包含有指向基类的指针(或“智能指针”)的容器来获得一个异常容器的效果。
- 指向容器内部的指针或引用的有效生命周期应该由容器的提供者来指定。理想情况下生命周期应该是“直到容器被摧毁为止”;有着“直到下一次调用该操作”这样的生命周期应该被避免。
- 迭代器应该指向元素之间或者元素本身。在这一点上,由容器组成的集合应该达到共识。
- 模版中每个成员都可以对其模版参数加以限制。
- 将公用的逻辑独立出来并被所有实例共享可以使得常用模版性从中获益。
- 模版可以被特化。特化可以一直推迟到链接时才被确定。
- 预期的用户应该通过阅读手册中的第一行就可以判断某个库是否可以被使用。
- 在我们的文档中,类名是其中最重要的部分。我们应该审慎的选择它们,并和其他人进行交流以确保它们对其它人也有着同样的含义。
- 频繁的使用断言来即时的终止有问题的程序。
- 除非知道数组的大小上限,否则我们应该避免使用固定大小的数组。
- 为库提供一个除错版本
- 不要使用诸如Object 这样容易和其它库相冲突的名字来作为我们的类名。
- 使用静态成员来避免将名字导入全局名字空间。
- 使用对象来管理内存,不要手动来管理它们。
- 我们应该了解,进程在推出时可能不会去摧毁所有的自动对象。
- 即使里面的元素没有析构函数,我们也要用delete[] 来删除数组。
- 使用工具来查找内存泄漏的情况:编写自己的malloc 和 free ,或者使用商业化产品。
- 为了找到对已摧毁对象的使用,我们应该在析构函数中为对象中的数据成员赋予一些明显无效的值。
- 程序的正确性要比其速度更重要。
- 我们应该去度量性能,而不是猜测。
- 记录下库函数的复杂度,尤其是那些不是以常量时间运行的函数。
- 对算法进行改进通常都可以获得更大性能的提高。
- 在对性能进行调整前,首先得确定导致性能问题的原因而不是程序中的bug。
- 使用诸如Pool的类来构建快速的特定于类的内存分配器。
- 请牢记Tiemann 法则。
第10章 异常
- 异常是c++的一个新的特性,它正在不断变化中;请时刻关注标准化组织在这个领域的法则。
- 不要将异常用于正常的程序控制流程中。
- 在理解了异常将被人或者是程序来检测的基础上再设计你的异常类。
- 在你的异常类的相关联设计中使用继承。
- 不要把类名取为Exception。
- 项目进度表必须为学习曲线预留余地。
- c++是一门优秀的通用编程语言,但对于特殊的应用程序来说,存在这更适用的编程语言来实现它。
- 请逐步的采用c++,一开始将它作为更好的c来使用,然后开始采用数据抽象,最后使用面向对象的编程方式。
- 在使用c++的设计过程中,前期将会变得负担更重。
- 不要同时使用所有的特性。
- 设计应采用迭代的方式来进行。
- 使用类要比构建它们容易。
- 尽量使用通用库
- 用于处理高层次抽象的语言需要更多的编译时间。
- 我们程序的目标代码会变得更大。
- 除非我们计划对其进行新的开发,否则不要将已有的c代码转换为c++代码
- 重用不是一种业余爱好。
本文是关于C++编程的高级程序员惯用法读书笔记,涵盖抽象设计、模板高级用法和异常处理等多个方面。强调了设计迭代过程、边界条件的考虑、避免公共数据、智能指针的使用、模版特化和异常的安全使用等核心要点,旨在提高C++编程的效率和代码质量。

761

被折叠的 条评论
为什么被折叠?



