代码结构
头文件和源文件的关系
头文件(.h / .hpp)
头文件主要存放:
函数声明
cppint add(int a, int b); // 只声明,不实现类定义 - 类的结构和接口
cppclass Calculator { public: int add(int a, int b); int multiply(int a, int b); };宏定义、常量定义
cpp#define MAX_SIZE 100 const double PI = 3.14159;模板声明
内联函数(简单函数直接写在头文件里)
源文件(.cpp)
源文件主要存放:
函数实现 - 具体怎么做
cppint add(int a, int b) { return a + b; }类的成员函数实现
cppint Calculator::add(int a, int b) { return a + b; }全局变量的定义
cppint globalCounter = 0; // 这里是定义
代码如何跨文件调用
示例结构:
project/
├── math_utils.h (头文件 - 菜单)
├── math_utils.cpp (源文件 - 厨房)
└── main.cpp (主程序 - 顾客)cpp
#ifndef MATH_UTILS_H // 防止重复包含
#define MATH_UTILS_H
// 声明函数
int add(int a, int b);
double calculateCircleArea(double radius);
#endifcpp
#include "math_utils.h"
#include <cmath>
// 实现函数
int add(int a, int b) {
return a + b;
}
double calculateCircleArea(double radius) {
return 3.14159 * radius * radius;
}cpp
#include <iostream>
#include "math_utils.h" // 包含头文件
int main() {
int sum = add(5, 3); // 调用其他文件中的函数
std::cout << "Sum: " << sum << std::endl;
double area = calculateCircleArea(2.0);
std::cout << "Area: " << area << std::endl;
return 0;
}编译和链接的过程:
编译阶段(每个.cpp独立编译):
编译器: main.cpp + math_utils.h → main.o (目标文件) math_utils.cpp + math_utils.h → math_utils.o- 编译器看到
add()的声明,知道有这个函数 - 但不知道函数的具体实现在哪里
- 编译器看到
链接阶段:
链接器: main.o + math_utils.o → 可执行程序- 链接器找到
add()函数的实际位置 - 把所有目标文件"缝"在一起
- 链接器找到
重要规则总结:
- 头文件只放声明,源文件放实现(内联函数除外)
- #include 相当于复制粘贴 - 把头文件内容插入当前位置
- 避免循环包含 - 头文件互相包含会导致编译错误
- 使用头文件保护 -
#ifndef ... #define ... #endif防止重复定义 - 变量声明用 extern:cpp
// header.h extern int globalVar; // 声明 // source.cpp int globalVar = 10; // 定义
为什么这么设计?
- 分离接口和实现 - 使用者只看头文件就知道怎么用
- 提高编译速度 - 修改一个.cpp文件时,其他文件不需要重新编译
- 代码重用 - 多个源文件可以包含同一个头文件
- 模块化开发 - 不同的人可以同时开发不同的模块
记住:头文件是"做什么"的说明书,源文件是"怎么做"的具体实现。