[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的头文件.只是这里最 ...
随机推荐
- Day6 - D - Tree 园丁的烦恼 HYSBZ - 1935
很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题, ...
- 6 应用Nginx之后
以上的问题,涉及到Varnish
- 1 初识JVM
- Django(十一)视图详解:基本使用、登录实例、HttpReqeust对象、HttpResponse对象
一.视图(基于类的视图) [参考]https://docs.djangoproject.com/zh-hans/3.0/topics/class-based-views/intro/ 1)视图的功能 ...
- 指令——pwd
完整的指令的标准格式:Linux通用的格式 #指令主体(空格) [选项](空格) [操作对象] 一个指令可以包含多个选项,操作对象也可以是多个. 指令pwd: 用法:#pwd(print workin ...
- python基础笔记:判断与循环
判断: #根据身高为1.75,体重为65的小明的bmi输出小明的身材 h=1.75 w=65 bmi=w/(h*h) if bmi<18.5: print('过轻') elif bmi<= ...
- redis以服务模式开机启动
第一步 修改redis为后台启动 vim /usr/redis/redis.conf #路径根据实际情况决定 # By default Redis does not run as a daemon. ...
- SpringBoot+Jpa测试自增时报错Springboot-jpa Table 'sell.hibernate_sequence' doesn't exist
解决办法: @GeneratedValue(strategy = GenerationType.IDENTITY) 如图所示:
- ActorFramework教程对比及规划
牢骚太盛防肠断,风物长宜放眼量. 一.引子 昨天的文章,本来就是想写写ActorFramework的教程内容,结果写着写着偏了,变成了吐槽. 首先,声明一下,自己从未参加过任何LabVIEW培训班,也 ...
- 三十一、SAP中的循环和判断图标和表格的混用
一.代码如下 二.显示结果如下