设为首页 加入收藏

TOP

C++编码规范(二)
2015-07-20 17:25:37 来源: 作者: 【 】 浏览:14
Tags:编码 规范
狎昵关系

18. 异曲同工的类

19. 不完善的程序库类

20. 纯稚的数据类

21. 被拒绝的遗赠

22. 过多的注释

具体内容请参考《重构 改善既有代码的设计》, 在写代码的过程中,加红的几个是特别需要注意的

编译设置

在高警告级别进行编译,使用VC编译器应将警告级别打到最高4级,并设置将警告作为错误

宁要编译时和连接时错误,而不要运行时错误

项目设置include, lib路径使用相对路径,不要使用绝对路径

debug编译生成的是名称后加d ,如(debug是xxxd.exe, release是xxx.exe)

头文件

正确使用头文件可令代码在可读性、文件大小和性能上大为改观。

头文件以.h作扩展名

#define保护

所有头文件 都应该使用#define防止头文件被多重包含(multiple inclusion),命名格式为: _ _ _H_

为保证唯一性,头文件的命名应基于其所在项目源代码树的全路径。例如,项目foo中的头文件foo/src/bar/baz.h按如下方式保护:

#ifndef FOO_BAR_BAZ_H_

#define FOO_BAR_BAZ_H_

#endif // FOO_BAR_BAZ_H_

注:不要使用#pragma once来防止重复包含,因为该指令是vc特有的,它是一个编译器指令,其它的编译器不保证能支持它,而#ifndef是语言层面的, 只要是支持c++的编译器, 都支持,跨平台,兼容性更好。

头文件依赖

使用前置声明(forward declarations)尽量减少.h文件中#include的数量,加快编译速度。

内联函数

?有当函数?有10行甚至更少时才会将其定义为内联函数(inline function)。

注:滥用内联将导致程序变慢。

函数参数顺序

定义函数时,参数顺序为:输入参数在前,输出参数在后。

包含文件的名称及次序

将包含次序标准化可增强可读性、避免隐藏依赖(注:隐藏依赖主要是指包含的文件编译)

头文件包含次序如下:C库、C++库、其他库的.h、项目内的.h。

实现文件(如dir/foo.cpp)包含次序如下:

dir2/foo2.h(优先位置,详情如下)

C系统文件

C++系统文件

其他库头文件

本项目内头文件

在包含文件里不要使用.(当前目录)和..(父目录),如:

#include “../abc.h” // 不要这样使用

作用域

命名空间

在.cpp文件中,允许甚至提倡使用未具名命名空间,以避免运行时的命名冲突: namespace {

// .cc 文件中 // 命名空间的内容无需缩进

enum { UNUSED, EOF, ERROR }; // 经常使用的符号

bool AtEof() { return pos_ == EOF; } // 使用本命名空间内的符号EOF

} // namespace

然而,不特定类关联的文件作用域声明在该类中被声明为类型、静态数据成员或静态成员函数,而不是未具名命名空间的成员。像上文展示的那样,不具名命名空间结束时用注释// namespace标识。

不能在.h文件中使用未具名命名空间。

不要在头文件中或者#include之前使用using namespace

局部变量

将局部变量尽可能置于最小作用域内,在声明变量时就将其初始化。

全局变量

禁止class类型的全局变量

内建类型的全局变量是允许的,

当然多线程代码中非常数全局变量也是被禁止的。

永远不要使用函数返回值来初始化全局变量。

原因:c++标准在全局变量的构造函数、析构函数和初始化顺序上没有保证。因此每次生成都可能会有变化,从而导致难以觉察的BUGS。

对于全局的字符串常量,使用C风格的字符串,而不要使用STL的字符串:

const char kFrogSays[] = “ribbet”;

虽然允许在全局作用域中使用全局变量,使用时务必三思。大多数全局变量应该是类的静态数据成员,或者当其?在.cpp文件中使用时,将其定义到未具名命名空间中

注:静态成员变量视作全局变量,所以,也不能是class类型!

如果一定要使用全局变量,请使用设计模式中的单件模式(singleton模式)。

C++类

用小类代替巨类

构造函数

类构造函数的初始化列表中成员变量初始化的顺序应该与在h头文件中声明的顺序一致。不要在构造函数体里进行赋值操作。

对单参数构造函数使用C++关键字explicit。

虚拟函数

避免在构造函数和析构函数中调用虚拟函数

继承

多用组合,少用继承

接口

接口定义如下:

class IFoo

{

public:

virtual ~IFoo(){};

virtual void dooo() = 0;

};

即含有纯虚函数,且实现虚析构函数的类。

接口类主要是为实现多态的。

操作符重载

尽量不要使用操作符重载

存取控制

将数据成员私有化,并提供相关存取函数

声明次序

在类中使用特定的声明次序:public:在private:之前,成员函数在数据成员(变量)前。

定义次序如下:public:、protected:、private:,如果那一块没有,直接忽略即可。

每一块中,声明次序一般如下:

1) typedefs和enums;

2) 常量;

3) 构造函数;

4) 析构函数;

5) 成员函数,含静态成员函数;

6) 数据成员,含静态数据成员。

编写短小函数

函数体尽量短小、紧凑,功能单一

智能指针

如果确实需要使用智能指针的话,scoped_ptr完全可以胜任。在非常特殊的情况下,例如对STL容器中对象,你应该只使用std::tr1::shared_ptr,任何情况下都不要使用auto_ptr。

引用参数

引用传递的参数必须加上const,如果要将参数传出,请使用指针。

缺省参数

禁止使用缺省函数参数。

异常

不要使用C++异常。

异常会导致程序控制流通过查看代码无法确定:函数有可能在不确定的地方返回,从而导致代码管理和调试困难。

异常的实用性可能会刺激开发人员在不恰当的时候抛出异常,戒者在不安全的地方从异常中恢复。

运行时类型识别RTTI

禁止使用RTTI, 单元测试程序除外。

类型转换

使用C++风格的类型转换, 不要使用C风格的类型转换。

1) static_cast:和C风格转换相似可做值的强制转换,或指针的父类到子类的明确的向上转换;

2) const_cast:移除const属性;

3) reinterpret_cast:指针类型和整型或其他指针间不安全的相互转换,仅在你对所做一切了然于心时使用;

4) dynamic_cast:除测试外不要使用,除单元测试外,如果你需要在运行时确定类型信息,说明设计有缺陷(参考RTTI)。

前置自增和自减

对简单数值(非对象)来说,两种都无所谓,对迭代器和模板类型来说,要使用前置自增(自减)。

const的使用

在任何可以使用的情况下都要使用const。

预处理宏

使用宏时要谨慎,尽量以内联函数、枚举和常量代替之,字符串化(##)除外;

0和NULL

整数用0,实数用0.0,?针用NULL,字符(串)用’/0’;

sizeof(sizeof)

用sizeof(varname)代替sizeof(type);

Boost库

只使用Boost中被认

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇改善C++程序的建议:语法篇1 下一篇SDUT 1941-Friday the Thirteenth..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C 内存管理 | 菜鸟教 (2025-12-26 20:20:37)
·如何在 C 语言函数中 (2025-12-26 20:20:34)
·国际音标 [ç] (2025-12-26 20:20:31)
·微服务 Spring Boot (2025-12-26 18:20:10)
·如何调整 Redis 内存 (2025-12-26 18:20:07)