作者:sdfqw4543gf | 来源:互联网 | 2024-12-22 12:03
我有一个类,它有两种可能的实现方式,具体取决于预处理器开关。为了处理这种情况,我在项目中创建了两个头文件:'src/CompSwitch1/class.h' 和 'src/CompSwitch2/class.h'。在我的标准包含文件中,我使用以下代码来选择正确的头文件:
#ifdef CompSwitch1
#include "CompSwitch1/class.h"
#elif defined(CompSwitch2)
#include "CompSwitch2/class.h"
#else
#error "必须指定 CompSwitch1 或 CompSwitch2"
#endif
这种方法适用于大多数需要两种版本的类。然而,在其中一个类上,我遇到了链接器错误(lnk2019:未解析的外部符号)。这个问题出现在 MS Visual Studio 2005 和 2008 中。
在 .h 文件的顶部,我测试了预处理器选项。此外,虽然这里只提到了头文件,但每个实现还有一个对应的 .cpp 文件,位于相应的目录中。
解决方案
#1
可能是你包含了其中一个类的头文件,但链接了另一个类的目标文件,或者两者都没有正确包含和链接。
#2
建议使用 #elif defined(CompSwitch2)
而不是简单的 #elif CompSwitch2
。这样可以确保即使定义为其他值也能正常工作。
#3
尝试在每个 cpp 实现文件中添加以下预处理器指令,以确保编译时使用的头文件与 cpp 文件一致:
// 在 compswitch1.cpp 中
#ifndef CompSwitch1
# error "包含的头文件不一致"
#endif
// 在 compswitch2.cpp 中
#ifndef CompSwitch2
# error "包含的头文件不一致"
#endif
如果编译了错误的头文件/cpp 文件对,应该会得到编译错误而不是链接错误,这更容易识别和修复。
另一种可能性是 cpp 文件根本未被编译。可以在 cpp 文件中加入消息 pragma,以确认它们是否被编译:
#pragma message( "正在编译 " __FILE__ )
还可以检查构建目录中是否有与 cpp 编译单元相关的目标文件。
#4
可以使用预处理后的 cpp 文件(所有包含和宏展开后的阶段)来诊断问题。在 VS 2008 中,右键单击解决方案资源管理器中的文件 -> 属性 -> C++ -> 预处理器,设置“生成预处理文件”为“带行号 (/P)”。然后再次右键单击文件并选择“编译”。这将在 cpp 文件所在的同一目录中生成扩展名为 .i 的文件。打开该文件查看实际包含的头文件。
此方法对于解决复杂的编译问题非常有用,例如系统头文件中的宏替换了代码中的某些内容。