理解 C++ 中的头文件和源文件的作用(3)

考虑一下,如果头文件中只包含声明语句的话,它被同一个 .cpp 文件包含再多次都没问题——因为声明语句的出现是不受限制的。然而,上面讨论到的头文件中的三个例外也是头文件很常用的一个用处。那么,一旦一个头文件中出现了上面三个例外中的任何一个,它再被一个 .cpp 包含多次的话,问题就大了。因为这三个例外中的语法元素虽然"可以定义在多个源文件中",但是"在一个源文件中只能出现一次"。设想一下,如果 a.h 中含有类 A 的定义,b.h 中含有类 B 的定义,由于类B的定义依赖了��� A,所以 b.h 中也 #include了a.h。现在有一个源文件,它同时用到了类A和类B,于是程序员在这个源文件中既把 a.h 包含进来了,也把 b.h 包含进来了。这时,问题就来了:类A的定义在这个源文件中出现了两次!于是整个程序就不能通过编译了。你也许会认为这是程序员的失误——他应该知道 b.h 包含了 a.h ——但事实上他不应该知道。

使用 "#define" 配合条件编译可以很好地解决这个问题。在一个头文件中,通过 #define 定义一个名字,并且通过条件编译 #ifndef...#endif 使得编译器可以根据这个名字是否被定义,再决定要不要继续编译该头文中后续的内容。这个方法虽然简单,但是写头文件时一定记得写进去。

C++ 头文件和源文件的区别 一、源文件如何根据 #include 来关联头文件

1、系统自带的头文件用尖括号括起来,这样编译器会在系统文件目录下查找。

2、用户自定义的文件用双引号括起来,编译器首先会在用户目录下查找,然后在到 C++ 安装目录(比如 VC 中可以指定和修改库文件查找路径,Unix 和 Linux 中可以通过环境变量来设定)中查找,最后在系统文件中查找。

#include "xxx.h"(我一直以为 "" 和 <> 没什么区别,但是 tinyxml.h 是非系统下的都文件,所以要用 "")

二、头文件如何来关联源文件

这个问题实际上是说,已知头文件 "a.h" 声明了一系列函数,"b.cpp" 中实现了这些函数,那么如果我想在 "c.cpp" 中使用 "a.h" 中声明的这些在 "b.cpp"中实现的函数,通常都是在 "c.cpp" 中使用 #include "a.h",那么 c.cpp 是怎样找到 b.cpp 中的实现呢?

其实 .cpp 和 .h 文件名称没有任何直接关系,很多编译器都可以接受其他扩展名。比如偶现在看到偶们公司的源代码,.cpp 文件由 .cc 文件替代了。

在 Turbo C 中,采用命令行方式进行编译,命令行参数为文件的名称,默认的是 .cpp 和 .h,但是也可以自定义为 .xxx 等等。

谭浩强老师的《C 程序设计》一书中提到,编译器预处理时,要对 #include 命令进行"文件包含处理":将 file2.c 的全部内容复制到 #include "file2.c" 处。这也正说明了,为什么很多编译器并不 care 到底这个文件的后缀名是什么----因为 #include 预处理就是完成了一个"复制并插入代码"的工作。

编译的时候,并不会去找 b.cpp 文件中的函数实现,只有在 link 的时候才进行这个工作。我们在 b.cpp 或 c.cpp 中用 #include "a.h" 实际上是引入相关声明,使得编译可以通过,程序并不关心实现是在哪里,是怎么实现的。源文件编译后成生了目标文件(.o 或 .obj 文件),目标文件中,这些函数和变量就视作一个个符号。在 link 的时候,需要在 makefile 里面说明需要连接哪个 .o 或 .obj 文件(在这里是 b.cpp 生成的 .o 或 .obj 文件),此时,连接器会去这个 .o 或 .obj 文件中找在 b.cpp 中实现的函数,再把他们 build 到 makefile 中指定的那个可以执行文件中。

在 Unix下,甚至可以不在源文件中包括头文件,只需要在 makefile 中指名即可(不过这样大大降低了程序可读性,是个不好的习惯哦^_^)。在 VC 中,一帮情况下不需要自己写 makefile,只需要将需要的文件都包括在 project中,VC 会自动帮你把 makefile 写好。

通常,C++ 编译器会在每个 .o 或 .obj 文件中都去找一下所需要的符号,而不是只在某个文件中找或者说找到一个就不找了。因此,如果在几个不同文件中实现了同一个函数,或者定义了同一个全局变量,链接的时候就会提示 "redefined"。

综上所诉

.h文件中能包含:

类成员数据的声明,但不能赋值

类静态数据成员的定义和赋值,但不建议,只是个声明就好。

类的成员函数的声明

非类成员函数的声明

常数的定义:如:constint a=5;

静态函数的定义

类的内联函数的定义

不能包含:

1. 所有非静态变量(不是类的数据成员)的声明

2。 默认命名空间声明不要放在头文件,using namespace std;等应放在.cpp中,在 .h 文件中使用 std::string

Linux公社的RSS地址https://www.linuxidc.com/rssFeed.aspx

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/a9005569a25131fd10eb6cc449961780.html