头文件应命名为my_math.hpp并放在源文件同目录或通过-i指定路径;引用用#include "my_math.hpp";必须加#include guard或#pragma once;头文件只放声明,定义移至.cpp;禁用using指令。

头文件该叫什么名字、放哪、怎么引用
头文件名建议用 .h 或 .hpp 后缀,纯 C++ 项目推荐 .hpp(避免和 C 头文件混淆);文件路径要能被编译器找到——要么放在源文件同目录,要么通过 -I 参数指定包含路径。引用时用 #include "my_math.hpp"(双引号),不是 (尖括号只用于系统/第三方头文件)。
必须加 include guard 或 #pragma once
不加防护会导致重复定义错误,比如多次 #include 同一个头文件后,编译器看到两遍 class Vector3 声明就报 redefinition of 'Vector3'。两种写法都行:
#ifndef MY_MATH_HPP #define MY_MATH_HPP // 你的声明放这里 #endif
或更简洁的:
#pragma once
注意:#pragma once 在主流编译器(GCC、Clang、MSVC)都支持,但极少数旧环境可能不认;#ifndef 更通用,宏名别用简单词如 UTILS_H,容易冲突,推荐用路径+文件名大写转下划线,比如 ENGINE_MATH_VECTOR3_HPP。
头文件里只能放声明,别放定义
函数体、全局变量初始化、模板以外的 static 变量定义,都得挪到 .cpp 文件里。否则多个源文件包含这个头,链接时会报 multiple definition of 'add'。
常见错误写法:
// ❌ my_math.hpp —— 这样写会链接失败
int add(int a, int b) { return a + b; } // 函数定义!
正确做法:
- 头文件只写声明:
int add(int a, int b); - 另建
my_math.cpp,里面写定义:int add(int a, int b) { return a + b; } - 编译时要把
my_math.cpp一起加入:比如g++ main.cpp my_math.cpp -o app
例外:内联函数、constexpr 函数、模板函数,定义可以留在头文件里——因为它们不产生独立符号。
using 指令和 using 声明别往头文件里塞
在头文件里写 using namespace std; 或 using std::vector; 是危险操作。一旦被其他文件包含,就会把命名空间污染扩散出去,可能引发命名冲突或意外重载。比如你头文件用了 using std::swap;,别人代码里又定义了 swap(MyType&, MyType&),ADL 就可能调错函数。
安全做法:
- 头文件里一律用全名:
std::vector、std::string - 如果实在想省事,在
.cpp文件的实现顶部加using - 或者只在函数内部用:
void foo() { using std::swap; swap(a, b); }
头文件是接口契约,越干净越可靠。多敲几个 std:: 换来的可维护性,远比少打字重要。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











