Monday, July 9, 2012

【转】写给自己的C++编程规范


    对于我这样一个C语言的程序员来说,编写C++的机会其实不太多。但是我还是比较喜欢写C++语言,原因主要有几个方面:(1)自己学C++语言的时间比较长了,也比较了解,如果从大一的时候算起,现在也有小十年了;(2)windows下面的开发工具确实很好用,比如调试器调用、汇编代码查看也方便,学起来其实没有什么障碍;(3)基于C++语言的开源项目还是比较多的,比如说的eMule、webkit、notepad++、libsvm,掌握好C++语言对自己的帮助还是挺大的。

    和很多朋友一样,我自己的C++学习也是非常曲折的,这其中主要有下面几个阶段。刚开始,在大一刚刚入学的时候,我们集中学习了C++的基本语法,其实我也不清楚为什么要在大学设置C++这门这么难的语言,其实对于很多工科的同学来说,C语言已经是绰绰有余了,况且能把C语言学好本身就已经很不错了。后面,随着C++的了解,我开始用MFC编写一些小程序,什么串口工具、聊天工具、FTP下载工具、图像处理工具等等,这个时候看得比较多的就是侯捷的《深入浅出MFC》。当然后来随着MFC使用的频繁,对C++语言的了解也更加深入,这个时候更多地关注C++语言的实现细节,什么《Effective C++》、《C++ Template》、《Inside the C++ object》、《Effective STL》,此时恨不得不自己会的所有技巧都用上,充分发挥C++的特性。等到工作之后,由于工作的关系更加偏重于实时操作系统,自己对编程语言有了新的认识,不再盲目追求语言的特性,而是更注重系统的稳定、项目的开发进度和语言本身的简洁和高效。无疑,在这些要求下面,C语言就是最佳的选择,因为你可以清楚地了解每一行语句后面CPU都帮我们做了些什么。我看过的很多操作系统代码,比如ucos、rt-thread、linux、vxworks都是用C语言编写的,很简洁也很高效。

    网上有位知名的朋友叫云风,早期在他写的书《我的编程感悟》当中也是对C++大加褒奖,可是在后来的工程实践中反而感觉到C语言才是最好用的语言。相信很多的朋友都有类似的经验。当然,不可否认C++还是存在很大的市场,但是它的应用范围和过去相比,确实是大大缩小了。一方面,精通C++的人实在是太少了,用好C++的人更是凤毛麟角;另外一方面,C++的学习代价、应用代价实在是很高,你没有办法要求项目组里边的每个人都有很高的C++应用水平,这是没有办法做到的,就算做到了,代价是十分昂贵的。所以,为了消除彼此成员之间的差别,很多时候C++的编程规范就变成了C语言的编程规范,这可以从google C++ style guide可以看出来。

    所以,今天这里写这篇文章,主要是就C++写一些自己的总结,谈谈自己的看法,欢迎各位提出宝贵意见。

(1) 总则
    a)尽量选择所有编译器都支持的C++标准
    b)必须了解类的内存分布结构
    c)必须了解编译器对C++的隐形操作
    d)指针是所有错误的来源,尽量用引用代替
    e)用const对入参、出参和类函数进行限制
    f)多用namespace限定类的作用范围
    g)少用C++的高级特性
    h)时刻在需要处理C文件的时候添加extern “C”
    i)string类是万恶之源,尽量少用

(2)头文件
    a)定义头文件的时候首先添加编译宏
    b)添加最少的头文件依赖
    c)头文件名争取和类名一致
    d)头文件中只包括类型定义、宏定义和函数声明
    e)类的头文件和实现文件一一对应

(3)命名
    a)类的命名按照首字母大写的格式进行,比如Parent
    b)宏按照全大写的格式进行,比如MAX
    c)函数按照小写进行,中间用连词号连接,比如get_max_number
    d)变量按照一个单词进行,比如number,index等等
    e)变量、函数多用static限定范围,类多用namespace限定范围

(4)函数
    a)杜绝可变参的函数,不利于编译器检查
    b)少用全局函数
    c)函数入参多用引用类型
    d)返回值多用引用类型,但是临时变量不能用引用
    e)全局函数少用重载,最好不用
    f)最好不用使用模板函数,即使使用也只限定于自己使用

(5)类
    a)少用继承,多用组合
    b)对于构造函数,多用explicit,防止编译器强行转换
    c)对于指针成员变量,务必注意拷贝构造函数和赋值函数的编写
    d)对于类指针,为了防止内存泄漏或者资源重复释放,最好自己管理,不要相信智能指针
    e)继承类中的析构函数要定义为virtual类型
    f)构造函数要简单,复杂的资源分配请在类成员函数init中定义
    g)对于全局类变量,相互定义之间不要存在依赖
    h)严格区分类指针的释放,注意delete和delete[]的区别
    i)对于类中锁的问题,可以利用类的构造、析构、引用特性解决
    j)多用class,少用struct

(6)类的高级特性
    a)不要使用算术符重载
    b)不要用模板,除非自己用,自己用也要少用
    c)不用使用C++中的typeid属性
    d)不要用异常
    e)不要用virtual继承
    f)不要用多类继承
    g)不用要stl,当类中存在指针变量的时候,stl很多时候是搞不定的,而vector、list、find、sort你是搞得定的

No comments:

Post a Comment