【OOP阅读】头文件
一、全面了解C++头文件中可以包含的内容。列举出相应的代码。
以下内容节选自《C++ Primer Plus》
浏览任何一个标准头文件都会使您对头文件中的信息类型有一个清晰的概念,头文件中常见的形式包括:
明显常量——典型的stdio.h文件定义EOF、NULL和BUFSIZE
宏函数——getchar()通常被定义为getc(stdin),getc()通常定义为复杂的宏
函数声明——头文件string…h包含字符串函数系列的函数声明。在ANSIC中,采用函数原型形式
结构模板定义——标准I/O函数使用FILE结构,该结构包含文件及文件相关缓冲区的信息。头文件stdio.h中存放FILE结构的声明
类型定义——可以使用指向FILE的指针作为参数调用标准I/O函数。通常,stdio.h用#define或typedef使得FILE代表指向FILE结构的指针。与之类似的,size_t和time_t类型也在头文件中定义。
另外,可以使用头文件来声明多个文件共享的外部变量。
代码示例
//names_st.h
//常量
#define SLEN 32
//结构声明
struct names_st{
char first[SLEN];
char last[SLEN];
};
//类型定义
typedef struct name_st names;
//函数原型
void get_names(names * );
二、上网搜索,研究C++头文件的包含顺序。
1) 列出《Google C++ 编程风格指南》中的观点,主要解决什么问题?
将包含次序标准化可增强可读性、避免隐藏依赖(hidden dependencies,注:隐藏依赖主要是指包含的文件编译),次序如下:C库、C++库、其他库的.h、项目内的.h。
项目内头文件应按照项目源代码目录树结构排列,并且避免使用 UNIX 文件路径.(当前目录)和…(父目录)。例如,google-awesome-project/src/base/logging.h应像这样被包含:
#include “base/logging.h”
dir/foo.cc 的主要作用是执行或测试dir2/foo2.h的功能,foo.cc中包含头文件的次序如下:
dir2/foo2.h(优先位置,详情如下)
C系统文件
C++系统文件
其他库头文件
本项目内头文件
这种排序方式可有效减少隐藏依赖,我们希望每一个头文件独立编译。最简单的实现方式是将其作为第一个.h文件包含在对应的.cc中。
dir/foo.cc和dir2/foo2.h通常位于相同目录下(像base/basictypes_unittest.cc和base/basictypes.h),但也可在不同目录下。
相同目录下头文件挄字母序是不错的选择。
举例来说,google-awesome-project/src/foo/internal/fooserver.cc的包含次序如下:
#include “foo/public/fooserver.h” // 优先位置
#include <sys/types.h>
#include <unistd.h>
#include <hash_map>
#include
#include “base/basictypes.h”
#include “base/commandlineflags.h”
#include “foo/public/bar.h”
包含文件的名称使用.和…虽然方便却易混乱,使用比较完整的项目路径看上去清晰、条理,包含文件的次序除了美观外,最重要的是可以减少隐藏依赖,使每个头文件在“最需要编译”对应源文件处)的地方编译,有人提出库文件放在最后,这样出错先是项目内的文件,头文件都放在对应源文件的最前面, 这一点足以保证内部错误的及时发现了。
2) 列出《C++编程思想》中的观点,主要解决什么问题?
在Thinking in C++中
Headers are included in order from “the most specific to the most general.” That is, any header files in the local directory are included first, then any of my own “tool” headers, such as require.h, then any third-party library headers, then the Standard C++ Library headers, and finally the C library headers.
The justification for this comes from John Lakos in Large-Scale C++ Software Design (Addison-Wesley, 1996):
Latent usage errors can be avoided by ensuring that the .h file of a component parses by itself – without externally-provided declarations or definitions… Including the .h file as the very first line of the .c file ensures that no critical piece of information intrinsic to the physical interface of the component is missing from the .h file (or, if there is, that you will find out about it as soon as you try to compile the .c file).
If the order of header inclusion goes “from most specific to most general,” then it’s more likely that if your header doesn’t parse by itself, you’ll find out about it sooner and prevent annoyances down the road.
意即“从最特殊到最一般”,在本地目录中的任何头文件首先被包含,然后是我们自己的所有“工具”头文件,随后是第三方库头文件,接着是标准C++库头文件和C库头文件。
好处是如果我们的头文件不被他自己解析,我们将马上找到它,防止麻烦事发生。
保证.h文件的组成部分不被他自身解析,可以避免潜在的使用错误。