包含防护提供了针对递归包含的保护,但它们无法防止相互包含的标头中数据结构定义之间的依赖关系。考虑以下代码:
// header.h #ifndef HEADER_H #define HEADER_H class A; class B { public: A* pA; }; #endif // HEADER_H
// source1.cpp #include "header.h" A* aPtr = new A;
// source2.cpp #include "header.h" B* bPtr = new B;
在此场景中,source1.cpp 包含 header.h,而 header.h 包含 source2.cpp(间接)。这个行为可以通过 include Guard 来阻止,但是编译器仍然会报错,因为 header.h 中没有定义类 A。
要解决这个问题,可以在 header.h 中使用前向声明:
// header.h #ifndef HEADER_H #define HEADER_H struct A; class B { public: A* pA; }; #endif // HEADER_H
这确保编译器知道类 A 的存在,而无需提供其定义。
包含防护可防止同一翻译单元(.cpp 文件)内出现多个符号定义。但是,它们不能防止跨不同翻译单元的多个定义。
考虑以下代码:
// header.h #ifndef HEADER_H #define HEADER_H int f() { return 0; } #endif // HEADER_H
// source1.cpp #include "header.h" int main() { f(); }
// source2.cpp #include "header.h" int main() { f(); }
在此示例中,函数 f()定义在 header.h 中。当 source1.cpp 和 source2.cpp 单独编译时,包含防护将防止每个翻译单元内出现多个定义。然而,当目标代码链接在一起时,链接器会检测到 f() 的多个定义。
要解决这个问题,可以使用 inline 关键字告诉编译器直接在函数定义处内联调用站点:
// header.h #ifndef HEADER_H #define HEADER_H inline int f() { return 0; } #endif // HEADER_H
或者,可以将函数定义移动到单独的 .cpp 文件中,以避免与其他翻译单元中的定义发生冲突。
以上是为什么 Include Guard 无法防止递归包含和多重符号定义?的详细内容。更多信息请关注PHP中文网其他相关文章!