头文件需用include guard或#pragma once防止重复包含,只放声明、类型定义和宏,不放变量或函数定义(inline/constexpr/模板除外);#include""查当前目录优先,直查系统路径;多包含导致编译慢,应前向声明、移实现头文件至.cpp、避免using namespace std。

头文件怎么写才能被 #include 正确识别
头文件不是随便起个 .h 后缀就能用的,关键在于「声明可见性」和「重复包含防护」。C++ 编译器看到 #include "xxx.h" 时,是直接把文件内容原样插进当前源文件里——如果没防护,多次包含会导致 redefinition 错误。
标准写法必须带头文件卫士(include guard)或 #pragma once:
#ifndef MY_MATH_H #define MY_MATH_H <p>int add(int a, int b); double square(double x);</p><h1>endif // MY_MATH_H
-
#pragma once更简洁,但属于非标准扩展(不过所有主流编译器都支持) - 宏名
MY_MATH_H要全局唯一,建议用项目名+文件名大写+_H组合 - 头文件里只放声明(函数、类、extern 变量)、类型定义(
struct、using)、宏,**不要放变量定义或函数实现**(除非是 inline 或 constexpr)
#include "" 和 #include 的区别到底在哪
区别不在语法,而在编译器查找路径顺序。用错会导致 fatal error: xxx.h: No such file or directory。
-
#include "my_header.h":先在当前源文件所在目录找,再按编译器默认系统路径找(适合项目内头文件) -
#include <vector></vector>:直接跳过当前目录,只查系统/标准库路径(适合 STL、第三方库头文件) - 混用会出问题:比如把自定义头文件写成
#include <my_header.h></my_header.h>,而没把路径加进-I参数,就找不到
实操建议:自己写的全用 "";系统或第三方库全用 ;C 标准库头文件如 stdio.h 用 ,对应的 C++ 版本如 <cstdio></cstdio> 也用 。
立即学习“C++免费学习笔记(深入)”;
为什么定义放到头文件里会链接失败
因为 #include 是文本复制,如果在头文件里写了 int global_counter = 0;,每个 .cpp 包含它都会生成一个定义,链接时出现 multiple definition of 'global_counter'。
- 变量定义必须且只能出现在一个
.cpp文件里;头文件中用extern int global_counter;声明即可 - 函数实现同理:头文件里只写
void log_message(const char* msg);,实现在log.cpp里 - 例外:
inline函数、constexpr变量、模板(包括函数模板和类模板)可以安全地放在头文件里——它们的设计语义就是允许多次定义
头文件依赖太多导致编译慢,怎么减负
每个 #include 都会让预处理器复制整个文件内容,依赖链越深,单个 .cpp 编译越慢。常见症状是改了一个底层头文件,整个项目重编。
- 优先用前向声明(forward declaration)代替
#include:比如只需要指针/引用参数,就不用包含整个类定义,写class Widget;就够了 - 把只在实现里用到的头文件(如
<sstream></sstream>、<chrono></chrono>)移到.cpp里,别塞进头文件 - 避免在头文件里
using namespace std;——它会污染所有包含该头文件的翻译单元,还可能引发命名冲突 - 大型项目考虑模块(C++20 modules),但目前 MSVC / Clang 支持度尚不统一,
#include仍是主力
最常被忽略的一点:头文件里 #include 的顺序本身不影响正确性,但影响可维护性——把最具体的(本模块头文件)放第一,然后是项目内其他头,最后是系统头,这样能早发现本头文件是否过度依赖外部定义。


















