- 前言
- 多文件编译
- 模块化
- 文件结构
- 头文件.h
- 头文件结构
- 源文件.cpp
- 后记
本篇继续C++学习总结。
本篇将探讨C++中,变量与函数的内存模型,以及在多文件程序中的关系。先从多文件编译方法开始。
多文件编译 模块化由于大型程序的编译非常耗时,将所有代码写在一个源文件里是不现实的。通常做法是,把结构,类,符号常量等声明放在一个文件中,把具有相同功能的函数放在另一个文件中,把实际运行的程序单独放在一个文件中,形成不同的模块。
文件结构一般把C++程序分为三部分:头文件,源文件,程序入口文件。
头文件.h头文件包含内容:
- 函数声明
#define
宏定义- const符号常量
- 结构声明(定义)
- 类声明(定义)
- 函数模板声明(定义)
- 内联函数定义
函数定义和变量声明不能放在头文件中,否则如果另外两个头文件包含了该头文件,程序入口包含这两个头文件,就会报redefined
的错误。
内联函数与const变量是例外,也应当放在头文件中。
其它文件如果需要头文件里的函数、结构、类等声明,则可以直接通过#include
头文件来使用。
注意:实际操作中,结构和类定义也会一并放在头文件中,这也可能造成上述redefined
问题;函数模板的声明与定义也会放在头文件中,否则容易出现模板篇中提到的undefined reference
问题,但这也可能造成redefined
问题。
注意:#include
将在标准头文件目录下查找;#include "xxx.h"
首先在当前工作目录下查找,如果没有找到.h文件,再到标准目录下查找。
在一个文件中,只能将同一个头文件包含一次,否则很容易出现上面的redefined
问题。要解决该问题,首先要知道文件编译中#include "xxx.h"
干了什么。
#include
:预编译器接收#include
指令,把#include "xxx.h"
替换为xxx.h
文件中的内容。
因此,如果包含同一头文件两次,而头文件又刚好具有结构、类、函数模板的定义,就报redefined
错误。
为了防止重定义,可以通过下面示例的头文件结构来避免:
// example.h
#ifndef EXAMPLE_H_
#defined EXAMPLE_H_
struct myStruct{
int a;
float b;
bool c;
};
void func1(int a);
int func2();
#endif
如果引用该example.h
的源文件之前没有宏定义EXAMPLE_H_
,则宏定义EXAMPLE_H_
,并进行结构定义和函数声明等操作。之后再重复包含example.h
时,EXAMPLE_H_
已被宏定义,就不会重复包含头文件的内容。
此外,头文件包含还有一些比较常见的约定:
- 尽量不在头文件中包含其它的头文件,特别是自定义头文件。
- 尽量在同名源文件中包含其它的头文件,而不是在同名头文件中包含。
普通源文件示例:
#include "example.h"
void func1(int a){
a = 1;
}
int func2(){
return 1;
}
普通源文件主要是定义同名头文件中声明的函数。
程序入口文件示例:
#include "example.h"
void main(){
func1(0);
func2();
}
程序入口文件必须要包含使调用函数的头文件,否则报error: xxx was not declared
错误。
编译只编译.cpp文件。首先预编译把每个.cpp文件的头文件替换,注释删去,宏定义替换,条件编译;然后把每个.cpp文件编译成汇编码文件,再汇编成机器码文件,最后链接。
后记下篇继续记录C++的内存模型。