# 头文件与分离编译

URL: https://caijiao.org/cpp/project/multi-file
Source: docs/cpp/project/multi-file.md
Description: 本节介绍 C++ 中的头文件使用方法、头文件的作用，以及如何通过分离编译提高代码的组织性和可维护性。

在 C++ 中，头文件（Header Files）用于声明函数、类、常量等，在源代码文件之间共享信息。通过分离编译，可以将代码划分为多个文件，提高代码的模块化、可重用性和维护性。

## 头文件的作用

头文件通常包含函数声明、宏定义、常量、类声明等。它们的主要作用是使不同的源文件能够共享一些公共的信息和声明。

### 示例代码：头文件使用

假设有一个计算矩形面积的函数，定义在头文件中。

**`Rectangle.h`（头文件）**

```cpp
#ifndef RECTANGLE_H
#define RECTANGLE_H

class Rectangle {
public:
    Rectangle(double w, double h);
    double area() const;
private:
    double width;
    double height;
};

#endif
````

**`Rectangle.cpp`（源文件）**

```cpp
#include "Rectangle.h"

Rectangle::Rectangle(double w, double h) : width(w), height(h) {}

double Rectangle::area() const {
    return width * height;
}
```

**`main.cpp`（主文件）**

```cpp
#include <iostream>
#include "Rectangle.h"

int main() {
    Rectangle rect(5.0, 3.0);
    std::cout << "Area: " << rect.area() << std::endl;
    return 0;
}
```

在这个例子中，`Rectangle.h` 声明了类 `Rectangle` 的接口，`Rectangle.cpp` 定义了具体的实现，`main.cpp` 包含了头文件 `Rectangle.h` 来使用类。

## 头文件保护

为了防止头文件被多次包含，通常使用预处理指令 `#ifndef`、`#define` 和 `#endif` 来保护头文件。这样可以确保头文件在同一源文件中只被包含一次。

### 示例代码：头文件保护

```cpp
#ifndef MY_HEADER_H
#define MY_HEADER_H

// 头文件内容

#endif
```

这种保护机制是通过定义一个宏 `MY_HEADER_H` 来避免重复包含同一个头文件。如果该宏已经定义，则不会再次包含文件内容。

## 分离编译的概念

分离编译是指将源代码拆分成多个文件（通常是 `.cpp` 文件），每个文件可以独立编译。每个源文件都会包含对应的头文件，通过链接器将它们链接成一个最终的可执行文件。分离编译使得编译过程更高效，且便于团队协作开发。

### 优点：

* **加速编译**：修改一个 `.cpp` 文件时，只需要重新编译该文件，而不必重新编译所有源文件。
* **模块化**：将不同功能的代码拆分到不同的文件，增加代码的可读性和可维护性。
* **重用代码**：多个项目可以共享相同的头文件和源文件。

### 示例代码：分离编译

假设我们有以下三个文件：

* **`Rectangle.h`**：包含 `Rectangle` 类的声明。
* **`Rectangle.cpp`**：包含 `Rectangle` 类的实现。
* **`main.cpp`**：包含 `main` 函数。

在编译时，我们分别编译 `Rectangle.cpp` 和 `main.cpp`，然后通过链接器将它们链接成一个可执行文件。

```bash
g++ -c Rectangle.cpp     # 编译 Rectangle.cpp，生成 Rectangle.o
g++ -c main.cpp          # 编译 main.cpp，生成 main.o
g++ Rectangle.o main.o -o main  # 链接生成可执行文件 main
```

这样，只有修改了 `Rectangle.cpp` 或 `main.cpp` 中的内容时，才会重新编译相关文件，极大提高了编译效率。

## 总结

* 头文件用于声明函数、类等，以供源文件共享。
* 使用头文件保护避免头文件重复包含。
* 分离编译通过将代码拆分为多个源文件，提高编译效率和代码维护性。
* 分离编译适合大规模项目，减少了修改时的重新编译范围。
