编程之雅(C++编程准则)
来源:互联网 发布:销售数据采集通知 编辑:程序博客网 时间:2024/04/29 23:45
这些编程准则有一些是个人的编程经验,当然,我可没那么多经验,大部分都是各个大师总结出来的,我就是整理一下。
宏观:
- 将C++视为C、面向对象C++、模版C++、STL C++组成的语言联邦。
- 任何人不得添加任何东西到STL命名空间
- 不要轻易忽略编译器的警告
- 一定程度的使用测试驱动的开发方法
- 软件实体(类、模块、函数)应该是可扩展的,但是不可修改的
- 多采用敏捷的设计方法(个体和交互胜过过程和工具、可以工作的软件胜过面面俱到的文档、客户合作胜过合同谈判、响应变化胜过遵循计划)
- 经常性的交付可以工作的软件,交付的时间间隔越短越好
- 在整个项目开发期间,业务人员和开发人员必须天天都在一起工作
- 围绕被激励起来的个人来构建项目
- 在团队内部,多进行面对面的交流
- 提倡可持续的开发速度
- 使要构造的系统最简单(不要设计不需要的功能,不要过分设计)
- 最好的架构、需求和设计出自于自组织团队
- 每隔一段时间,团队会在如何才能更有效的工作方面进行反省,然后相应的对自己的行为进行调整
- 结对编程是一种比较好的选择
- 不能容忍重复的代码
- 持续的对代码进行重构
- 要做计划游戏
- 高层模块不应该依赖于底层模块。二者都应该依赖于抽象
- 尽可能的保证:抽象不应该依赖于细节,细节应该依赖于抽象(任何变量都不应该持有一个指向具体类的指针或引用;任何类都不应该从具体类派生;任何方法都不应该覆写它的任何基类中已经实现了的方法)
- 每个编程单元尽可能的向使用者提供使用承诺:例如资源回收保证、数据一致性保证、无异常保证
- 尽可能的在程序中处理所有可能的异常,而且尽可能的精细。(try...catch)
- 应该让程序体面的退出:在出现非计划内问题时自动产生dump文件。(利用SetUnhandledExceptionFilter调用MiniDumpWriteDump)
- 要先设计好类,建好各个类的文件,才能写代码。
- 用pragma once代替h文件头
类:
- 让接口容易被正确使用,不易被误用
- 设计class犹如设计type
- 将成员变量声明为private
- 尽量不要让类支持隐式类型转换
- friend成员函数是类接口的一种表现方式,但能避免使用就尽量避免
- 避免使用handles指向对象内部成分
- 慎重使用inline(小函数的确该用inline,但是考虑到inline函数无法调试,所以应谨慎)
- 确定public继承表现出is-a关系(即Liskov替换原则,永远可以用派生类取代基类)
- 避免覆盖继承而来的名称(基类函数重载,派生不重载,则其他覆盖;派生重载基类函数,则基类函数覆盖;变量也可以覆盖)
- 区别接口继承和实现继承(纯接口(virtual=0),接口+朴素实现(virtual=0+实现),接口+强制实现(non-virtual),以上为public继承,private继承全部是为了继承实现,而不继承接口)
- 根据上一条,只要出现virtual,就尽可能让它=0(成虚基类)
- 根据上上条,派生类不应该覆写non-virtual函数
- 绝不重新定义继承而来的缺省参数值
- private继承意味着继承实现,是composition,实现的是has-a逻辑。protected继承尽量少用。两种继承在设计层面完全没有意义,只是实现层面的代码重用。
- 凡是独立的对象都必须有非0大小(空对象会安插一个char)
- 一个类只负责一件事
- 一个类只提供一种内聚的接口(不应该让用户依赖于他们不使用的方法)
- 类内部的类型定义尽量放在public,否则不能作为返回值
- 类中的大属性都应该用智能指针(或返回STL时应使用move语意)
- 凡是类内私有变量加m前缀,凡事类似私有仿函数,加or后缀
- 静态成员初始化函数用静态类替代,可以顺便用个functor
四大函数(构造函数、拷贝构造、赋值、析构)
- 若有多态继承体系,基类析构函数尽量声明为virtual
- 如果类内new了对象,并且该类负责delete,则必须要定义拷贝构造函数和赋值操作符。
- 若不想使用编译器自动生成的函数,就该默认拒绝(将其声明在private或protected)
- 别让异常逃离析构函数,C++不喜欢析构函数吐出异常
- 绝不在构造函数或析构函数中调用virtual函数(当然其他函数调用virtual可以实现template method等有趣的模式)
- 拷贝函数应该确保拷贝了对象内所有成员和基类部分
- 不要以某个拷贝函数去实现另外一个拷贝函数(一个是copy函数,一个是copy assignment函数),应该把共同部分放在第三个独立函数
函数:
- 尽量将函数参数声明为const
- 另operator =返回一个*this的引用,并且在operator =中处理自我赋值
- 函数参数的构造顺序不确定,所以不要在函数参数中执行new操作,或将多个函数参数都用函数来表示(否则若一个发生异常,其他有可能不会执行)。
- 尽量用传递const 引用代替传值
- non-member,none-friend函数有封装性好,跨类型操作等能力,因此在需要的时候没有必要局限于把函数全部放到类里的传统规则。
- 若所有参数都需要类型转换,请为此采用non-memeber函数(典型的是双目操作符重载)
- 凡是需要对指针参数做提领操作,都需要检查是否为BULL
- 发布版程序维持程序的勉强工作比crash更好;debug版让程序尽量crash。(例如对NULL指针的提领)
代码布局:
- 头文件尽量不要包含头文件,尽可能的用前置声明。
- 类的声明和实现应该分开(template没有export可以用时得谨慎)
- 若必须要在同一文件中交叉引用定义,则可考虑类中类
- 所有类都该有自己的名称空间。
杂项:
- 尽可能用const enum inline 替换#define
- 尽可能使用const
- 确定对象调用前已先被初始化。(包括基本对象、类对象、类成员)
- 使用引用计数型智慧指针时,应该注意RCSPs无法打破环状引用
- 成员使用new和delete时应采用相同的形式
- 尽可能延后变量定义式的出现时间(Singleton)
- 尽可能少用转型操作,(reinterpret_cast,static_cast,const_cast太危险,dynamic_cast效率太低),但如果要转型,尽量用C++的*cast转型关键字。
- 输入流的getline尽量用全局getline函数。(可以用string)
- 不用临时变量,方便调试
- 轻量级对象应尽量多用临时对象
- 引用只用于立即处理,若需要长久保存,则得用堆
- 数值类型转化要用显式,尽量避免用隐式
模版
- 大项目中,尽量不要使用显式实例化
- 尽量使用包含模型组织模版代码
- 模版函数所有重载版本的声明都应位于被调用位置之前
- 模版函数的重载应只改变参数数或显式指定模版参数
- 模版参数两个>之间要求有空格
- 不得不用template不能采用分离模型时,对成员模版函数的特化必须在类外部用inline特化,否则会有重复定义问题。
模版构造函数不能在类内定义,必须要在类外定义。如果有模版构造函数的需求,尽量全部在类体外const inline定义(支持export的话可以考虑)
资源管理:
- 一旦使用了资源,必须归还,并且谁用谁归还(包括内存、文件描述器、互斥锁、图形界面中的字型和笔刷、数据库连接、网络socket)
- 用对象来管理资源
- 资源取得的时机便是初始化的时机。
- 在资源管理类中小心coping行为
- 在资源管理类中提供对原始资源的访问
RAII
STL:
- 可以用for_each来避免显示使用迭代器
- std内部是深拷贝
设计模式:
- 全局唯一对象尽量用Singleton,而不是用static
- 可以用non-virtual Interface的方式实现template method
- 用tr1::funtion实现strategy
- 编程之雅(C++编程准则)
- C语言编程准则之稳定篇
- C++编程准则(1)
- C++编程准则(2)
- C++编程准则(3)
- 嵌入式C编程32条准则
- 嵌入式C编程32条准则
- Thinking in Java 附录之编程准则
- ACE编程准则全记录(一)--反应器
- Java编程准则
- Java编程准则
- C++编程准则(1)
- C++编程准则
- Java编程准则
- C++编程准则
- Java编程准则
- C++编程经典准则
- 编程工作准则
- linux自动登录邮箱发邮件
- java面向对象4
- 前端页面弹窗插件lhgDialog
- 小小的蚂蚁很强大(蚂蚁算法MFC实现)
- 这四种最常见的菜 千万别用来下酒
- 编程之雅(C++编程准则)
- Android Service 通知Activity更新界面的方法
- w3cshool之JavaScript 基础
- 博弈论基础知识
- 加密与解密
- Android Handler详解
- 未来物联网时代安防企业如何获得话语权
- spring 自定义注解
- 一个简易的发送垃圾电子邮件