[C/C++]编程规范一:头文件篇
一般来说,每一个.cc或者.cpp文件对应一个头文件(.h文件),当然,也有例外,例如一些测试单元或者main文件,头文件的一些规范可以令代码可读性、程序的性能等大为改观,所以还是要注意头文件的规范问题。
一、#define保护
所有头文件为了防止文件被多重包含(multiple inclusion),一般就需要#define保护。#define保护的格式如下:
<PROJECT>_<PATH>_<FILE>_H_
例如:
#ifndef FOO_BAR_BARZ_H_
#define FOO_BAR_BARZ_H_
...
#endif //FOO_BAR_BARZ_H_
这个是比较老的一个做法了,所以很多编译器基本都是可以兼容的,但是还有另一个语句也是可以起到相同作用,但是一些太老的编译器据说用不了的(但是我好像没遇到过),VS下好像默认新建一个类的头文件就会用这个新的:
#program once
这一种相对于第一种的好处是,不通过#define一个变量来起到防止重复包含,所以,不存在重复变量的问题,#define后面的变量在同一个工程里是不能重复的,重复的话是只认一个的,就可能导致另一个文件编译的时候被排除。
二、头文件依赖
在头文件中减少包含其他头文件,改用前置声明(forward declarations),理由是:头文件被包含的同时会引入一项新的依赖(dependency),只要头文件被修改,代码就要重新编译,如果你的头文件包含了其它头文件,这些头文件的任何改动都将导致那些包含了你的头文件的代码重新编译。
使用前置声明就是在头文件中添加:
class Foo;
然后在对应的源文件中包含对应的头文件
#include <Foo.h>
可以这么做的几种情况:
1)、将数据声明为指针(Foo*)或者引用(Foo&);
2)、参数、返回值为Foo的函数只声明不定义;
3)、静态数据成员可以被声明为Foo,因为静态数据成员的定义在类定义之外;
但是,如果你的类是Foo的子类或者包含类型为Foo的非静态成员数据,则必须包含头文件。
补充说明,什么是声明,什么是定义,一般在头文件中经常看到一个函数,有返回值有输入参数,但是没有主体,或者一个变量声明为指针,但是没有new等操作,像这样的就是声明:
Foo *pFoo;
void setInputNumber(int num);
然后是定义,定义的话就是有函数主体,或者说就有变量的内存操作,包括非指针变量的声明也已经包含了定义,像这样的:
int nInputNumber;
int nCount = 0;
pFoo= new Foo();
void setInputNumber(int num)
{
nInputNumber = num;
}
三、内联函数
当函数小于10行的时候可以定义为内联函数(inline function)。
定义:当函数被声明为内联函数后,编译器会将其内联展开,无需像通常的函数调用机制一样来调用内联函数。
优点:可以令目标代码更高效。适合存取函数或一些较短的关键代码。
缺点:滥用内联适得其反,内敛较大代码(如果编译器允许),将增加代码量;
不可用或者尽量不要用内联函数的情况:
1)、超过10行代码;
2)、析构函数;
3)、递归函数(可能大多数编译器不支持);
4)、包含循环或者switch语句的函数;
四、头文件包含实现代码
一般来说,头文件是只包含声明,而不要包含实现代码的,但是用到内联函数或者函数模板的话就需要将代码实现写在一起,为了可读性,是可以新建一个后缀为-inl.h的头文件,专门用于存放内联函数和模板函数,这样可以增强代码可读性。
需要注意,这样的头文件也要加#define保护的。
五、函数参数顺序(Function Parameter Ordering)
顺序:输入参数在前,输入输出参数居中,输出参数在后。
或者:输入参数在前,输入输出参数居中,输出参数在后,控制参数垫后。
输入参数一般为传值或者常数引用(const references),输出或者输入输出参数一般为传非常数指针(non-const pointers),有些参数是输入参数,但是属于控制变量意义的参数,那我是觉得应该放最后面的。
六、包含头文件顺序
如果我有一个命名为Foo.h的头文件以及一个对应的Foo.cpp的源文件,那么,头文件中的包含顺序应该是:
C库 > C++库 > 其他库的.h文件 > 项目内的.h文件;
而源文件中的包含顺序应该是:
#include "Foo.h" > C库 > C++库 > 其他库的.h文件 > 项目内的.h文件
还有一点强迫症的可以将同目录下的头文件按首字母顺序来排列。
补充说明,#include ""和#include <>的区别:
1)、#include <>引用的是编译器的类库路径里面的头文件;一般编译器会在编译器设置的include目录和系统中的INCLUDE环境变量中找头文件;一般用于标准文件;
2)、#include ""引用程序目录的相对位置的头文件;一般是先从当前文件所在的文件夹内找,找不到再去编译器设置的include目录或者系统的INCLUDE环境变量中找;一般用于自定义的文件。
结语
编程规范一方面是给机器看,提高代码的效率,另一方面也非常重要的用于给人看,提高人的效率。上述规范不一定就完全正确或者必须这么做,只是给个建议,看别人代码是超级累的一件事,简直想大呼这TM写的啥啊,何况更可怕的是看完发现这TM是我自己写的代码,想死的心都有了,利人终利己,就算出错了也好意思找别人帮忙看啊。
川口雨晴风复止,蜻蜓上下鱼东西。
[C/C++]编程规范一:头文件篇的更多相关文章
- arpa/inet.h所引起的Segmentation fault及网络编程常见的头文件
最近在学习Linux网络编程方面的知识,感觉还是有些困难.主要是对协议过程的理解,还有socket的API的理解不够深刻.今天复习编写了一个TCP的服务端和客户端的程序实现client.c从命令行参数 ...
- c/c++编码规范(1)--头文件
最近工作稍微轻松一点,就再学习了一下编码规范.遂记些笔记,以便查阅. 这次学习的是Google 开源项目风格指南中文版,地址是:http://zh-google-styleguide.readthed ...
- linux系统编程快速定位头文件的技巧之强大的grep命令
这个技巧来自于我的实际开发碰到的: inet_addr这个函数用于把ip地址转成网络字节序,他的原型:in_addr_t inet_addr(const char *cp); 返回值为一个in_add ...
- UNIX环境高级编程 apue.h头文件的配置
http://jimslinbing.blog.163.com/blog/static/85054319201292712414518/ 1.到http://www.apuebook.com下载源码2 ...
- C++编程规范和编译过程详解
前言:因为c++基础打得不牢,所以准备花点时间再学一下c++的基础知识,主要是看网易云课堂里面的免费课程,把一些知识点做个笔记记下来. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...
- 头文件intrins.h
intrins.h 在C51单片机编程中,头文件INTRINS.H的函数使用起来,就会让你像在用汇编时一样简便. 内部函数 描述 _crol_ 字符循环左移 _cror_ 字符循环右移 _ir ...
- C51单片机头文件和启动文件
STARTUP.A51//启动文件. 清理RAM.设置堆栈等.即执行完start.a51后跳转到.c文件的main函数 <reg51.h> //特殊寄存器的字节地址和位地址,sfr定义字 ...
- C++编程规范之23:头文件应该自给自足
摘要: 各司其责:应该确保所编写的每个头文件都能够独自进行编译,为此需要包含其内容所依赖的所有头文件. 如果一个文件包含某个头文件时,还要包含另一个头文件才能工作,就会增加交流障碍,给头文件的用户增添 ...
- google C++编程风格指南之头文件的包括顺序
google C++编程风格对头文件的包括顺序作出例如以下指示: (1)为了加强可读性和避免隐含依赖,应使用以下的顺序:C标准库.C++标准库.其他库的头文件.你自己project的头文件.只是这里最 ...
随机推荐
- mysql 权限管理 grant revoke
grant all privileges on database.table to 'user'@'ip' identified by 'passwd' with grant option; g ...
- java字符,字符串,数字之间的转换
string 和int之间的转换 string转换成int :Integer.valueOf("12") int转换成string : String.valueOf(12) ch ...
- PowerShell的一些资料整理
年后准备把一些公司的一些祖传脚本给重新弄下,之前的脚本是bat写的,又臭又长,这次就不准备补窟窿了.打算用powershell重写下,这里就整理了一些相关的技术资料. 入门教程: 入门教程可以首选国内 ...
- Xcode8.0+和最新的Xcode9.0beta安装Alcatraz插件
1.安装Alcatraz 1.1终端中输入 rm -rf ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins/Alcatraz ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-road
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- Golang的运算符-逻辑运算符
Golang的运算符-逻辑运算符 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.逻辑运算符概述 !: 非运算符,表示NOT(有种取反的意思),如"!ture" ...
- DRF项目之通过业务逻辑选择数据集和序列化器
在REST后台开发中,我们需要通过业务逻辑来选择数据集或者序列化器. 选择数据集: # 重写get_queryset实现通过业务逻辑选择指定数据集 def get_queryset(self): '' ...
- jQuery原理系列-css选择器实现
jQuery最强大的功能在于它可以通过css选择器查找元素,它的源码中有一半是sizzle css选择器引擎的代码,在html5规范出来之后,增加了document.querySelector和doc ...
- SPOJ ANARC05H 计数DP
给定一个数字串,问有多少种拆分方法,题目所谓的拆分,就是分成若干个子块,每个块的和 即为各个数字相加,当前块的和一定要小于等于后面的块的和 比如1117 就有这些[1-117], [1-1-17], ...
- [NOIP2017] T4 跳房子 DP+二分
Description 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一.跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 n 个格子,这些格子都在同一条直线 ...