使用array(QT下用QVarLengthArray)代替和vector代替原生数组,除非与外部库交互,不然不要直接操做内存(即暴露data的接口)程序员
关于array和vector初始化麻烦的问题,在VS2010下使用boost::assign库,在VS2015下则使用list initial的语法算法
使用array和vector代替原生数组之后,能够很好找到越界的地方数据库
尽可能不要直接操做内存, 若是须要使用内存和字符串操做,尽可能使用memset_s, memcpy_s,尽可能使用_s结尾的函数json
若是须要初始化数组,使用int a[COUNT] = {0}这种语法(但实际上尽可能不要直接使用原生数组)网络
在进行memory操做的时候,须要使用is_pod验证下变量类型是否pod类型数据结构
使用STL的算法代替手写的算法,日常用到的算法STL里面或者QT的算法模块里面都有多线程
构造函数必定要初始化C原生类型的数据成员函数
使用C++风格的转换,不要用C语言方式的转换
dynamic_cast,当继承树不同的时候,编译器将会报错,或者转换失败,原生的C语言编译正确而且转换正确
static_cast,会有转换类型检查,好比子类往父类强转,编译期检查
使用QVariant代替void*
当进行强转错误的时候,QVariant能直接返回错误的数值
使用强枚举
便于查看代码
若是传入错误,能够直接让编译器报错
编写测试,系统检测架构图,而后 将测试用例自动化
分离数据和界面
经常使用的宏定义,放在Global里面,相似于qt_global文件
IOCEAN里面常常会有重复的宏定义,好比PI,好比无效的HDG,须要防止这种状况
多用const
const的类成员函数,告诉使用者这个函数将不会对类成员进行改变,在写代码若是有改变,也能直接报错
const的参数
const的引用参数
在计算出一些临时的参数后,若是肯定这个参数不会再改变了,也建议用const
使用Q_ASSERT, assert, static_assert断言处理逻辑上不可能出现的状况
若是已经使用Q_ASSERT,表示这种状况下不须要测试
在发送网络的数据的时候,有时候发送的是纯二进制数据,可是后续用户可能会在这个数据加入非POD数据,可使用static_assert( std::is_pod<>::value) 来确保这个结构体是纯二进制数据
字符串和数据结构库统一使用QT的库,好比QLIST,QVector,而非std::list,std::vector
为了防止混用
与QT库比较好结合
使用scoped_pointer和shared_pointer来代替原始指针
专一业务编写,而非内存管理以及排错
便于调试,若是是局部变量的指针,在release会直接被优化成地址,没法显示信息,若是是shared_pointer或者scoped_pointer则不会
全部建立的线程,都要设置名称,方便查询线程的用处
资源应该遵循谁申请谁释放的原则,不该该把一个资源胡乱传递(将会致使最后资源不知道谁释放谁持有)
CPP里面的模块变量使用static const而不是只有const声明
使用static const代替宏定义
记录log,log不只仅是开发的时候调试使用,更是在用户机子上分析错误的重要工具,如今咱们大部分的log都是维持在debug级别,应该要多编写warning和error级别的log
因为不少状况下,一些错误的状况没法复现,也没法分析,特别在部署到用户机子上之后,很难到现场排查
一开始不必定要记录log,根据本身的经验判断是否须要log,可是随着开发进度的增长,会出现一些莫名其妙的错误,好比网络不稳定,内存不稳定致使问题,排查完问题后,在发生问题的根源记录下log
有一个问题,常常会掉线,由于网络有时候波动会比较大,写数据库会很慢,这个时候若是新客户端连上去后会发送全部的数据,将会致使心跳包处理不及时,客户端会主动断开,排查完缘由后,在初始化发送数据的地方编写一段代码,当初始化超过必定的时间后,将会记录一个warning,下次发生这种状况,直接经过log来排查分析
有时候一些模块由于须要排队处理数据,可是数据处理不即时,致使数据一直存储在buffer里面,可是按照正常状况下,不该该发生这种状况。排查完问题之后,应该在插入buffer的地方写一个判断代码,当buffer大于多少后,给出一个warning
底层数据管理类不要直接暴露内部的状况,而且将对底层数据操做的算法提取出来写在管理类里面,而不是你们都写一个相同的算法
在代码重构阶段,一旦底层数据直接暴露,那么将会很难修改
一旦代码有相关联的模块,这种方式比较好处理,好比删除元素,须要把相关联的数据都删除掉,若是没有把deleteTarget封装成一个接口,那么须要查找全部相关联的代码,把这个业务的代码再写一遍
防止大部分人写了相同的代码
全部数据只有一份,包括内存里面的数据和网络消息,如今一个数据结构常常定义了2-3份数据,包括内存里面的,序列化成网络消息的
组合,继承与接口设计
继承要保证是一个is-a的类型,即保证一样的逻辑操做能够用在同一个接口上面,而不须要进行大量的转换,若是逻辑操做出现大量的类型转换,考虑是否继承出现了问题
信号
将业务组合成一个函数,单独的功能写成一个单独的模块,而后在一个函数里面将这些业务组合起来
若是有大量相同的逻辑代码,考虑是否能够提取成一个函数或者模板, 特别是当一个逻辑不会增长依赖的时候
若是使用了大量的dynamic_cast,而且有相同逻辑的代码,考虑是否能够将这个行为抽象成一个接口
通用的库弄成一个lib,好比SQL之类的库
非通用的库,可是一些项目里面要用到的,新建一个解决方案,解决方案里面有一个共用的库
- 语义明确的多线程
SQL模块 select(tablename).where("i < 7").and("j > 8").or("x < 2")
使用std::function代理SIGNAL和SLOT的绑定
将不须要制做成索引的数据使用json保存,而不是另外建立一个表而后关联过去
尽可能使用designer进行布局
C++11
RAII
Move语义