编码的法则
文章平均质量分 79
此专栏是2014年已出版著作《编码的法则:C++程序员不可不知的101条实用经验》连载,每天发布一条准则
@一鸣惊人
这个作者很懒,什么都没留下…
展开
-
实用经验 101 提高(改善)代码可读性的措施
良好的注释、规范的变量命名,可显著的提高程序的可读性。可读性好的代码更容易被理解和维护;可读性好的代码,可显著降低程序的开发成本。这种成功包括程序员的沟通和代码的维护。原创 2021-12-06 20:46:54 · 434 阅读 · 0 评论 -
实用经验 100 改善C++程序运行效率的措施
深刻理解影响C++性能的各种因素。在编程时小心这些因素给你带来的负面影响;谨慎的使用C++的继承、多态等高级特性。他们在给带来便利的同时,也会你带来性能的缺失。原创 2021-12-06 20:33:24 · 1558 阅读 · 0 评论 -
实用经验 99 试着在代码中使用设计模式
设计模式是前人经验的结晶,可以帮助我们优化设计,降低耦合。因此在实际设计过程中可尽量的使用设计模式。原创 2021-12-06 20:19:42 · 299 阅读 · 0 评论 -
实用经验 98 避免使用“聪明的技巧”
“聪明的技巧”对“技巧”要求太高。一般程序员无法理解。也影响了代码的可读性和可维护性。所以,请最好避免使用这种“聪明的技巧”。原创 2021-11-22 21:18:10 · 257 阅读 · 0 评论 -
实用经验 97 C++为何引入命名空间?
我们都知道在一个作用域中定义的每个标志符在该作用域中应该是唯一的,独一无二的。但对于庞大,复杂的系统应用程序而言,这个要求有时候很难达满足。对于庞大的应用程序,有些标识符几乎无可避免的发生冲突,这种标志符冲突问题被称之为“命名空间污染问题”。使用命名空间,你可以定义你自己的命名空间,这样可避免程序开发中发生的名字冲突。解决命名空间污染问题。原创 2021-11-22 21:08:51 · 854 阅读 · 0 评论 -
实用经验 96 可执行文件*.exe(*.dll)剖析
可执行文件,指一种内容可被电脑解释为程序的电脑文件。通常可执行文件内,含有以二进制编码的微处理器指令,也因此可执行文件有时称为二进制档。这些二进制微处理器指令的编码,于各种微处理器有所不同,故此可执行文件多数要分开不同的微处理版本。每个C++可执行程序都包含文件头,代码段,数据段。他们是怎么存储的这是你需要掌握的。了解可执行文件布局,掌握程序中各部分分别存储在什么位置。可以指导我们编写出更优秀的代码。原创 2021-11-20 17:06:25 · 2098 阅读 · 3 评论 -
实用经验 95 检测和定位内存泄露的技巧
项目中由于各方面因素,总是有人抱怨存在内存泄漏,系统长时间运行之后,可用内存越来越少,甚至导致了某些服务失败。内存泄漏是最难捉摸也最难检测到的错误之一。 要养成良好习惯,保证malloc/new和free/delete匹配。时刻小心内存泄漏,你可以借用专业的检查工具检测并定位内存泄露。这样可显著提供你的程序开发效率原创 2021-11-20 16:47:35 · 323 阅读 · 0 评论 -
实用经验 94 虚函数的实现原理
C++中的虚函数作用主要是实现多态机制。关于多态,简而言之就是用基类指针指向其派生类的实例,然后通过基类指针调用实际派生类的成员函数。这种技术可让基类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。掌握C++的虚函数实现机制,有助于我们编写出安全易用的C++程序。同样我们也需要明白C++虚函数存在的安全性问题,避免使用这些不安全的机制。原创 2021-11-17 23:27:25 · 179 阅读 · 0 评论 -
实用经验 93 合理的使用断言(ASSERT)
使用断言在软件开发阶段及测试阶段,可帮助我们检查程序中的一些错误,并提供有用的信息。合理的使用断言,以提升程序开发和问题定位的效率。常用的断言有两种:一种是动态断言,即大家所熟知的C标准库的assert()宏,一种是C中的静态断言,即在编译期间检查。本使用经验主要介绍动态断言。原创 2021-11-14 12:07:34 · 818 阅读 · 0 评论 -
第13章 C++高级特性
本章将讨论C++的一些高级特性。他们在某些适当的场景下是有用的,但并不是所有的场景下都必须。没有掌握他们,你可以写出运行良好的程序,但是,如果你掌握并使用了他们,你所编写的代码会在扩展性,可维护性方面,可能更有优势。笔者将带领大家从最基础的断言开始,讨论C++程序实现的一些特征。也许你以前从未关注过这些东西,但没关系,我们从现在开始学习掌握。因为掌握他们是你迈向C++高级程序员的必经之路。如果你想成为C++高级开发人员,掌握他们是最基本的特质。原创 2021-11-14 11:55:39 · 866 阅读 · 0 评论 -
实用经验 92 区分函数模版与模版函数,类模版和模板类
模板就是实现代码重用机制的一种工具,它可实现类型参数化,即把类型定义为参数, 从而实现了代码的可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。在使用模板概念时,经常会遇到这4个概念:函数模板,模板函数,类模板,模板类。这4个概念非常类似,也经常被我们所误用,本使用经验将主要讲述他们的差异。原创 2021-11-11 23:33:06 · 1527 阅读 · 0 评论 -
实用经验 91 区分继承、模版还有组合
区分模板和继承,当对象的类型不影响类中函数的行为时,选择使用模板,当对象的类型影响类中函数的行为时,选择继承而不选择模板。区别继承和组合,如果对象关系是is kind of 关系时选择继承,如果是a part of关系时选择组合。原创 2021-10-21 23:25:08 · 199 阅读 · 0 评论 -
实用经验 90 将模版的声明和定义放到同一个文件
模板是多态的静态实现方式,模板可以最大限度降低同质冗余代码,增加代码的维护性。模板实现有三种方法,声明和实现在同一个头文件中;声明和实现分离,包含头文件;使用export实现分离。但是在这三种实现方式中,声明和实现在同一个头文件中,是最优实现方式。原创 2021-10-20 19:29:11 · 207 阅读 · 0 评论 -
第12章 模版和泛型
你设计的两个类,除了成员变量数据类型之外,其他所有操作和实现完全相同。这些问题都可通过模板和泛型解决。面向对象所依赖的多态是运行时的多态,而泛型模板所依赖的多态是编译时的多态或参数式多态。本章就来讨论模板和泛型,也许这些议题无法保证你成为模板编程的专家,但却有可能使你会成模板编程的高手。原创 2021-10-19 23:45:24 · 118 阅读 · 0 评论 -
实用经验 89 关于虚赋值的问题
将重载赋值运算符实现声明为virtual函数,称为虚赋值。赋值运算符声明为虚函数是合法的,但是虚赋值却不合理。尽量避免使用虚复制,而通过原型模式替代实现对象的复制拷贝。原创 2021-10-19 23:19:44 · 191 阅读 · 0 评论 -
实用经验 88 虚函数重载的陷阱
如果你的项目不支持C++1,不要试图尝试重载虚函数,你会为此付出代价的,如果你的项目支持C++11,那另当别论。原创 2021-10-19 23:06:31 · 335 阅读 · 0 评论 -
实用经验 87 切记继承过度滥用
在设计过程中,过广或过深的继承都不是良好设计。类型职责划分不清楚是造成这种继承主要原因。对继承滥用保持警惕,同时警惕常理逻辑在软件设计中的负面影响。对于“指数级”继承膨胀问题,我们应需寻找合适的解决方案,以防类似问题继续蔓延原创 2021-10-06 10:01:16 · 417 阅读 · 0 评论 -
实用经验 86 绝对不要重新定义继承而来的缺省参数
绝对不要重新定义继承而来的缺省参数,采用NVI方案:令基类的一个public non-virtual函数调用一个private virtual函数,后者可被派生类重新定义。可让non-virtual函数指定缺省参数,而private virtual函数负责真正实现工作。采用NVI这种方式,用户可采用静态的方式从基类类型的接口取得参数默认值,而派生类也可自由的变更函数的行为,而不用担心什么缺省初始化物了。原创 2021-10-01 08:42:22 · 144 阅读 · 0 评论 -
实用经验 85 不要重新定义继承而来的非虚函数
重定义继承而来的非虚函数导致的最明显的现象就是函数覆盖。任何情况下都要禁止重新定义继承而来的非虚函数。以防产生函数覆盖现象。原创 2021-09-30 22:24:46 · 281 阅读 · 0 评论 -
实用经验 84 区分接口继承和实现继承
无论是接口继承还是实现继承,都是public继承的范畴。public继承可分为两部分:接口继承和实现继承。同一种public继承方式,在不同代码环境中表现出不同的特性。这蕴含了深刻的面向对象设计理解和实现机制。通过本博客的学习你会掌握接口继承和实现继承的差异性。原创 2021-09-13 21:56:48 · 785 阅读 · 0 评论 -
实用经验 83 确保public继承是“is-a”关系
public 继承意味着“is-a”。任何使用基类Base的地方都可以被派生类Derived完全替换,因为每一个Derived Object 都是一个 Base Object。在public继承设计中,我们需要考虑常识,同时也要兼顾is-a的客观概念。只有这样设计出的继承和多态才能满足实际编程的需要。原创 2021-09-11 00:13:15 · 233 阅读 · 0 评论 -
实用经验 82 区分overloading、overriding、hiding的差异
OOP存在重载(overloading)、重写(overriding)、隐藏(hiding)3个概念。他们非常相似,也容易混淆。三者的差异可从作用域,函数名,参数,返回值,有无virtual等方面来理解。原创 2021-09-09 23:15:44 · 226 阅读 · 0 评论 -
实用经验 81 谨慎的使用private继承
public继承可视为is-a关系。私有继承仅展示的是Drived依靠Base而实现这种概念,除此之外别无其他了。private继承意味只有实现部分被继承, 接口部分应略去。如果classes之间的继承关系是private,编译器不会自动将一个Derived 对象转换为一个Base对象,而pubic展示的是Drived是一种Base。原创 2021-09-08 19:48:27 · 130 阅读 · 0 评论 -
实用经验 80 理解派生类构造/析构运行原理
对象的构造和析构扮演着对象创建和释放的角色。如同现实世界中的其他事物一样,对象同样有自己的创建顺序和释放流程,尤其在存在继承和虚继承的对象体系中,对象的构造和析构更显得尤为重要。对象构造析构遵循规则如下:派生类构造,先构造所有基类(基类构造的顺序为其声明的顺序),然后才构造当前派生类;派生类如存在成员对象,成员对象会先被构造,然后才运行构造函数构造当前派生类原创 2021-09-04 11:03:06 · 170 阅读 · 0 评论 -
实用经验 79 提防对象切片
如果一个派生类对象向上强制转化为基类,用的是传值的方式,而不是指针和引用,那么,这个派生类对象在向上转化后,将会被切分成基类对象,也就是说,派生类中独有的成员变量和方法都被切分掉了,只剩下和基类相同的成员变量和属性。这个派生类对象被切成了一个基类对象。这就是对象切片问题,本文将详细讲述对象切片的相关陷阱。原创 2021-09-01 19:50:28 · 138 阅读 · 0 评论 -
实用经验 78 谨慎的使用多继承
多继承一直是OOP世界一个敏感而备受争议的话题。在先进OOP语言的大世界中,仅有C++和Eiffel坚持支持多继承机制,其他的基本上都持反对的态度。拥护者认为多继承更能自然的塑造世界,而反对者认为多继承不仅效率低下,而且存在单继承不存在的复杂性问题。但是多继承不会给程序带来多大好处,反而会增加无尽的复杂度和维护的高难度。所以除非有必要,一般不推荐使用多继承。原创 2021-08-30 20:46:56 · 172 阅读 · 0 评论 -
实用经验 77 明晰public,protected,private三种继承差别
继承是C++中实现多态的重要方法,通过继承机制,可利用已有的数据类型来定义新的数据类型。所定义的新的类类型不仅拥有新定义的成员,而且还同时拥有旧的成员。C++支持public,protected和private三种继承方式,请明确知道3者的区别和可见性。除非必要请不要实现多继承。多继承的强制类型转换会导致对象切片问题。原创 2021-08-27 23:03:48 · 681 阅读 · 0 评论 -
实用经验 76 基类析构函数应声明为virtual函数
构造函数实现类对象的创建,析构函数完成对象删除时资源释放。两者成对出现,每个自定义类数据类型,都必须定义构造函数和析构函数。当定义对象时,类的构造函数会由编译默认调用,同样对象释放时,对象的析构函数由编译器默认调用,实现对象释放。但是多态情况下,将基类的析构函数声明为virtual,可以防止部分析构问题, 将基类的析构函数定义为纯虚函数,需保证此纯虚函数包含实现,以防在析构时抛出异常。原创 2021-08-24 21:04:27 · 496 阅读 · 0 评论 -
第11章 继承和多态
继承和多态是面向对象编程的基础。面向对象编程的关键思想是多态,而多态最基本的使用实现机制就是继承机制。本章的主题是继承和多态,他们是C++语言面向对象的灵魂所在。通过本章内容的学校,可帮助读者对继承和多态有一个更加深刻的认识。原创 2021-08-22 22:10:48 · 96 阅读 · 0 评论 -
实用经验 75 有些运算符重载应该成对实现
重载运算符,不仅== 和 !=、> 和 <、>= 和 <=要成对重载,+和+=,-和-=,*和*=,/和/=,%和%=也要成对重载原创 2021-08-22 21:18:52 · 110 阅读 · 0 评论 -
实用经验 74 重载操作符,类成员函数还是友元函数
重载操作符重载,使得程序表达更加直观,符合自然语言。对于双目运算符,建议采用friend函数。对于单目运算符,建议采用成员函数。双目运算符=只能重载为成员函数;单目运算符()、[]、->只能重载为成员函数。<<第一个操作数只能为ostream类型,所以<<运算符也只能为友员。原创 2021-08-21 08:25:04 · 481 阅读 · 0 评论 -
实用经验 73 重载operator=的陷阱
我们可通过重载内置的赋值运算符,实现用户自定义的数据类型也可具备内置数据类型的赋值运算能力,但是重载operator=需要考虑:自赋值问题,勿忘记复制所有成员。还有应为深拷贝还是浅拷贝。原创 2021-08-20 22:13:40 · 270 阅读 · 0 评论 -
实用经验 72 重载operator[]的陷阱
使用[]下标操作符,我们可像数组下标访问形式一样访问对象。这种操作方式简单而且形象,又方便理解。但是需注意operator[]下标操作符只能作为类的成员函数。同时在定义类的下标操作符时请定义两个版本。以适应const对象和非const对象。同时需要小心operator[]的陷阱。在重载时必须把这部分陷阱考虑进去,以防为此付出惨痛的代价。原创 2021-08-17 20:09:02 · 299 阅读 · 0 评论 -
实用经验 71 区别++/--操作符前置和后置差异
无论是++操作符还是—操作符,都有前置和后置之分。(++)自增和(–)自减是C++中最为特此的两个重载运算符,后置(++)自增和(–)自减均以前置(++)自增和(–)自减为基础实现。实现(++)自增和(–)自减,关键是掌握两种返回类型和返回类型的差异。原创 2021-08-15 14:51:31 · 1072 阅读 · 0 评论 -
实用经验 70 由重载&&、||和,操作符想到的
C++提供了比C语言更加强大的操作符功能。虽然操作符支持重载,但也不能成为重载的理由。重载操作符的目的是简化程序,而不引人新的问题,像||、&&和,还是不要重载的好。因为重载后的行为可能和你期望的行为不一样。原创 2021-08-15 00:41:32 · 97 阅读 · 0 评论 -
第10章 重载操作符
C和C++都定义了很多内置类型间的操作符,然而与C语言不同的是:C++语言支持重定义操作符作用于类类型对象的含义。有了操作符的重载,你可以像操作内置类型一样,操作你定义的类类型,从而避免复杂冗长的代码。这也需会让你喜出望外。但是类类型重载的操作符和内置操作符还是有差别的。本章将详细讲述重载操作符,希望通过本章的学习,读者能走出困扰,像专家一样将“操作符重载”玩弄于掌骨之间。原创 2021-08-15 00:08:59 · 83 阅读 · 0 评论 -
实用经验 69 理解常量成员函数
声明带有 const 关键字的成员函数指定,函数是 “只读”函数,在它被调用的时候不会修改对象。 一个常数成员函数不能修改任何非静态数据成员或调用不是常数的任何成员函数。声明常数成员函数,需在参数列表的右括号后放置const关键字。 声明和定义中均需要const 关键字。原创 2021-08-13 18:47:36 · 175 阅读 · 0 评论 -
实用经验 68 首选初始化列表实现类成员初始化
请选择初始化列表实现类成员的初始化,因为这种实现可提高程序的执行效率。如果类中包含引用或const成员。初始化类别是唯一可以为这些成员初始化的方法。因为在构造函数中无法对这类成员进行初始化工作。需要特殊说明的是:成员初始化,总是按照声明的顺序初始化,而不是按照初始化列表顺序初始化。原创 2021-08-12 22:41:06 · 181 阅读 · 0 评论 -
实用经验 67 关于对象复制的思考
对象复制,有拷贝构造,赋值操作等等。他们的目的都是一样的将数据从一个对象拷贝到另外一个对象。对象复制时,请记得复制对象的所有成员,及基类的所有成员。对于POD对象,您可以直接通过memset或memcpy实现对象的拷贝复制。原创 2021-08-11 22:42:12 · 126 阅读 · 0 评论 -
实用经验 66 class对象大小与什么有关系?
在C++中,对象大小牵涉着对象内存的使用。类对象的大小并不仅仅是对象中非静态数据成员的总和。其他因素包括内存对齐,虚函数,虚继承都影响类对象的大小。而类对象的大小影响因素不包括静态数据成员,因为类中的静态数据成员分布于全局存储区域。不占用类对象的空间。原创 2021-08-09 22:44:56 · 471 阅读 · 0 评论