重读金典------高质量C编程指南(林锐)-------第一章 文件结构

第一章  文件结构

      C/C++程序通常由两个文件组成,一个文件保存程序的声明,称为头文件,.h 文件。一个保存程序的实现,称为定义文件.c文件。

1.1 版权与版本的声明

版权和版本的声明位于头文件和定义文件的开头(参见示例1-1),主要内容有:
(1)版权信息。
(2)文件名称,标识符,摘要。
(3)当前版本号,作者/修改者,完成日期。
(4)版本历史信息。

实例如下:

/* 
* Copyright (c) 2001,上海贝尔有限公司网络应用事业部
* All rights reserved. 
* 
* 文件名称:filename.h 
* 文件标识:见配置管理计划书
* 摘  要:简要描述本文件的内容
* 
* 当前版本:1.1
* 作  者:输入作者(或修改者)名字
* 完成日期:2001年7月20日
* 
* 取代版本:1.0 
* 原作者  :输入原作者(或修改者)名字
* 完成日期:2001年5月10日
*/

1.2 头文件的结构

头文件由三部分组成:

1)头文件开头出的版权与版本声明

2)预处理块

3)函数和类结构声明

实例如下:

/* 
* Copyright (c) 2001,上海贝尔有限公司网络应用事业部
* All rights reserved. 
* 
* 文件名称:filename.h 
* 文件标识:见配置管理计划书
* 摘  要:简要描述本文件的内容
* 
* 当前版本:1.1
* 作  者:输入作者(或修改者)名字
* 完成日期:2001年7月20日
* 
* 取代版本:1.0 
* 原作者  :输入原作者(或修改者)名字
* 完成日期:2001年5月10日
*/ 
 
#ifndef GRAPHICS_H // 防止graphics.h被重复引用
#define GRAPHICS_H 
#include <math.h>   // 引用标准库的头文件
#include “myheader.h”  // 引用非标准库的头文件
void Function1(…); // 全局函数声明
class Box   // 类结构声明
{ 
}; 
#endif 

解释说明:

规则:1)为了防止头文件被重复引用,应当用 ifndef/define/endif  

解决了一个cpp中多次出现同一个.h文件时,只编译一次,这样提供了编程效率。

一、关键字:#ifndef,#define,#endif可以防止头文件被重复引用

结构是这样的:

如a.h头文件

#ifndef XX

#define XX

// 函数声明

#endif

第一次include这个头文件的时候由于XX还没有被define,所以满足#ifndef XX这个判断

那么执行它下面的内容 #define XX和他下面的函数声明;

如果由于编码者的不小心或者嵌套包含造成了这个头文件被多次引用;那么当编译到第二次#inlude的地方的时候由于不满足 #ifndef XX这个判断条件所以不执行后面的内容(#define XX和函数声明都不走)直接跳到#endif因此可以很好的防止头文件被重复引用

二、现在有一个大型的程序分为很多模块

每个模块中又有很多的函数

这样你肯定不可能知道他的全部函数中的代码

现在假如说

main.c文件中有这们两行代码:

#include<macro.h>

#include<key.h>

而macro.h有:

#include<key.h>

现在可以发现我们在main和macro中重复引用了key.h这样一个头文件

这就叫重复引用

防止重复引用的方法就是在每个头文件中加上ifndef/define/endif条件编译语句

头文件重复引用是指一个头文件在同一个CPP文件中被INCLUDE了多次,这种错误常常是由于INCLUDE 嵌套造成的。比如:

存在a.h文件

#include "dup.h"

.....

b.cpp文件如下

#include "a.h"

#include "dup.h"

....

此时就会造成重复引用。解决方法是在dup.h开头中加上:

#ifndef DUP_H

#define DUP_H

.......  //原来DUP.h中的内容

#endif

三、#include文件的一个不利之处在于一个头文件可能会被多次包含,为了说明这种错误,考虑下面的代码:
#include "x.h"
#include "x.h"
显然,这里文件x.h被包含了两次,没有人会故意编写这样的代码。但是下面的代码:
#include "a.h"
#include "b.h"
看上去没什么问题。如果a.h和b.h都包含了一个头文件x.h。那么x.h在此也同样被包含了两次,只不过它的形式不是那么明显而已。
多重包含在绝大多数情况下出现在大型程序中,它往往需要使用很多头文件,因此要发现重复包含并不容易。要解决这个问题,我们可以使用条件编译。如果所有的头文件都像下面这样编写:
#ifndef _HEADERNAME_H
#define _HEADERNAME_H
...
#endif
那么多重包含的危险就被消除了。当头文件第一次被包含时,它被正常处理,符号_HEADERNAME_H被定义为1。如果头文件被再次包含,通过条件编译,它的内容被忽略。符号_HEADERNAME_H按照被包含头文件的文件名进行取名,以避免由于其他头文件使用相同的符号而引起的冲突。

但是,你必须记住预处理器仍将整个头文件读入,即使这个头文件所有内容将被忽略。由于这种处理将减慢编译速度,所以如果可能,应该避免出现多重包含。

2)用#include<filename.h>格式来引用标准库的头文件(编译器将从标准库目录开始搜索)

3)用#include “filename.h”格式来引用非标准库的头文件(编译器将从用户工作目录开始搜索)

4)强烈建议头文件只存放声明,而不存放定义。

      在c++的语法中,类的成员函数可以在声明的同时被定义,并且自动成为内联函数,这样会带来书写上的方便,却造成风格的不一致。建议将成员函数的定义与声明分开写,不论函数体有多么小。

5)不提倡使用全局变量,尽量不要在头文件中出现extern int value  这类声明。

1.3   定义文件的结构

定义文件有三部分内容:

1)定义文件开头处的版权与版本声明

2)对一些头文件的使用

3)程序的实现(包括数据和代码)

实例:

/* 
* Copyright (c) 2001,上海贝尔有限公司网络应用事业部
* All rights reserved. 
* 
* 文件名称:filename.h 
* 文件标识:见配置管理计划书
* 摘  要:简要描述本文件的内容
* 
* 当前版本:1.1
* 作  者:输入作者(或修改者)名字
* 完成日期:2001年7月20日
* 
* 取代版本:1.0 
* 原作者  :输入原作者(或修改者)名字
* 完成日期:2001年5月10日
*/ 
#include “graphics.h” // 引用头文件
// 全局函数的实现体
void Function1(…) 
{ 
} 
// 类成员函数的实现体
void Box::Draw(…) 
{ 
}

1.4  头文件的作用

1)通过头文件来调用库功能,因为很多情况下,用户需要根据头文件的接口来调用库文件。而厂家只提供给你头文件和二进制的库。编译器会从库中提取相应的代码。

2)头文件能加强类型安全检查,如果某个接口被实现或被使用时,假如我们调用的方式与头文件不相同,编译器编译时会报错。这样可以大大减轻程序员的 调试与改错的负担。

1.5  目录结构

一个source 一个 include,这是为了当你的软件的头文件和定义文件比较多的时候,可以分别保存于不同的目录下,便于维护。

 

原文地址:https://www.cnblogs.com/zhuxuekui/p/3585228.html