不应在头文件中实现函数或定义对象
4.7 ID_definedInHeader
在头文件中定义的函数或对象会被引入不同的翻译单元(translate-unit)造成编译冲突。
定义为常量、内联、模板的函数或对象可不受本规则约束,静态函数或对象也不受本规则约束,但受规则 ID_staticInHeader 限制。
头文件是项目文档的重要组成部分,有必要保持头文件简洁清晰,头文件的主要内容应是类型或接口的声明。除非函数很简短,否则也不建议在头文件中内联实现,大段的函数实现会影响头文件的可读性。
注意,定义在头文件中的函数发生变化时,所有相关模块均需重新编译,会增加构建和维护成本,在使用动态链接库时这个问题尤为突出,如果库的导入者没有及时编译,可能会造成严重后果。在头文件中定义的函数是模块二进制接口的一部分,应合理规划以降低维护成本。
示例:
// In a header
int a[] = {1, 2, 3}; // Non-compliant
int foo() { // Non-compliant
return 1;
}
对于较为复杂的模板函数,应将其实现与声明分离,如:
// In a header
template <class T>
struct A {
T foo(T&); // Declaration
};
#include "A.imp"
// In A.imp
template <class T>
T A<T>::foo(T& p) { // Implementation
....
}
将模板函数的实现移入 .imp 文件中,再由主头文件包含即可,.imp 文件称为模板实现文件。