若x.h仅含函数声明,是否必须在x.cpp中引入?能否省略?
哈哈,这个问题戳中了很多C/C++新手的疑惑点——明明头文件里只有函数声明,我在x.cpp里已经写了对应的实现,为啥还要多此一举引入它?其实这背后全是编译器给你挖的坑,引头文件就是帮你提前踩坑的!
必须引入的核心原因
帮编译器做类型校验,提前揪错
你自己知道函数的参数、返回值类型,但编译器不知道啊!比如x.h里声明的是int calculate(int a, int b),你在x.cpp里不小心写成float calculate(int a, int b),要是没引x.h,编译器编译x.cpp的时候根本不会觉得有问题——直到链接阶段,其他文件调用这个函数时才会报错,那时候你要排查整个项目的函数签名,麻烦死了。引入x.h之后,编译器会直接对比声明和实现的签名,不一致立刻报错,把问题扼杀在编译阶段。杜绝隐式声明的大坑
尤其是C语言兼容场景下,如果你调用一个没声明的函数,编译器会自动给它做一个隐式声明:默认返回int,参数列表为空。要是你实际实现的函数是void print_message(const char* msg),隐式声明和实际签名完全不匹配,链接时必然失败,而且这种错误的提示信息往往很模糊,新手根本找不到问题在哪。引了头文件,编译器就知道函数的正确签名,不会瞎搞隐式声明了。维护代码的一致性和可读性
团队协作的时候,别人看x.cpp里引入了x.h,一眼就明白这个源文件是对应头文件里声明的函数实现,不用到处找函数声明的位置。而且后续如果有人修改了x.h里的函数声明(比如加了一个参数),只要x.cpp引了头文件,编译器立刻会提醒你同步修改实现,避免出现“声明和实现不一致”的隐形bug。
可以省略引入的极端情况
说实话,能省略的情况要么是歪门邪道,要么是特殊场景,不推荐日常这么干:
手动在x.cpp里重复写一遍函数声明
如果你在x.cpp开头手动写了和x.h里完全一样的函数声明,那确实可以不用引x.h。但这绝对是糟糕的做法!后续头文件的声明一旦修改,你很容易忘了同步x.cpp里的手动声明,到时候签名不一致,链接错误找上门,哭都来不及。函数是静态的,只在x.cpp内部使用
要是x.cpp里的函数是static修饰的,而且根本没在x.h里对外声明(也就是这个函数只给x.cpp自己用),那当然不用引x.h。但这种情况和题目里“x.h包含该函数声明”的前提不搭,因为这个函数根本没出现在头文件里。你就是想搞事情?
没有什么“编译优化”的理由,现代编译器根本不会因为少引一个头文件提速,反而会增加出错的概率,完全没必要省这一步。
内容的提问来源于stack exchange,提问作者Артём Гаркавый

