头文件中只应包含声明而非定义,否则因被多个源文件包含会导致重复定义错误;例如将void print_hello() { std::cout

头文件里只放声明,不放定义
很多人一拆文件就报 multiple definition 错误,根本原因是把函数实现(比如 void print_hello() { std::cout )直接写进了 <code>.h 文件。头文件被多个 .cpp 包含后,每个编译单元都生成一份函数体,链接时自然冲突。
正确做法是:.h 里只写函数声明、类声明、extern 变量声明;实现全扔进对应的 .cpp 文件。
-
utils.h:只含void print_hello(); -
utils.cpp:含#include "utils.h"和完整函数体 - 所有用到该函数的
.cpp都#include "utils.h",但只链接一次utils.o
类的声明和实现必须分离
C++ 类如果定义在头文件里又没加 inline 或模板修饰,也会触发重复定义。尤其注意成员函数——哪怕只有一行,也不要直接写在类体内(除非你明确要内联)。
常见错误写法:class A { void f() { std::cout → 这等价于隐式 <code>inline,但容易误导,且不利于调试和编译依赖管理。
- 把类声明放在
A.h(含成员函数声明) - 把所有非模板、非内联的成员函数实现在
A.cpp中 - 构造/析构函数也照此处理,哪怕空实现也要写在
.cpp里 - 若真需要内联,显式写
inline void f() { ... },但别滥用
main.cpp 只负责组装,不藏逻辑
初学者常把所有练习代码塞进 main.cpp,然后试图“拆”出一个 helper.cpp 却忘了改 main 的依赖。结果要么调不到函数,要么头文件路径错。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
关键检查点:
-
main.cpp只保留#include和main()调用,不写任何算法或数据结构实现 - 确保每个
.cpp都显式#include它真正需要的头文件(不要靠间接包含) - 编译命令要列出所有
.cpp:例如g++ main.cpp utils.cpp A.cpp -o app - 用
-I指定头文件路径,比如头在inc/下就加-Iinc
静态局部变量和匿名命名空间别跨文件共享
想在多个文件间共享一个计数器?别用 static int counter = 0; 写在 .cpp 顶层——这会让每个文件都有一份独立副本。同样,匿名命名空间里的东西也仅限本编译单元。
真正需要跨文件共享的状态,只有两种安全方式:
- 在
.h中用extern int counter;声明,在**且仅在一个**.cpp中定义int counter = 0; - 封装进类的静态成员变量(声明在头,定义在 cpp),由类统一管理生命周期
- 避免全局变量,优先用函数参数或对象成员传递状态
拆文件不是为了多建几个文件,而是让每个文件职责清晰、可独立编译、依赖明确。最常被忽略的是:头文件的包含守卫(#ifndef UTILS_H)和 .cpp 对头文件的严格依赖控制——少一个 #include 或多一个隐式依赖,都会在换编译器或加新文件时突然崩掉。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










