2019-02-15
什么是未定义的引用/未解析的外部符号错误,我该如何解决?

什么是未定义的参考/未解决的外部符号错误?什么是常见原因以及如何修复/预防它们? 编译C ++程序分为几个步骤,由2.2 指定(Keith Thompson的信用作为参考): 翻译语法规则的优先级由以下阶段指定[见脚注]。 如果需要,物理源文件字符以实现定义的方式映射到基本源字符集(引入行尾指示符的换行符)。[SNIP] 删除反斜杠字符(\)后面紧跟一个新行字符的每个实例,拼接物理源代码行以形成逻辑源代码行。[SNIP] 源文件被分解为预处理标记(2.5)和空白字符序列(包括注释)。[SNIP] 执行预处理指令,扩展宏调用,并执行_Pragma一元运算符表达式。[SNIP] 字符文字或字符串文字中的每个源字符集成员,以及字符文字或非原始字符串文字中的每个转义序列和通用字符名称,都将转换为执行字符集的相应成员; [SNIP] 相邻的字符串文字标记是连接的。 分隔标记的空白字符不再重要。每个预处理令牌都转换为令牌。(2.7)。由此产生的标记在语法和语义上进行分析并翻译为翻译单元。[SNIP] 翻译的翻译单元和实例化单元组合如下:[SNIP] 解析所有外部实体引用。链接库组件以满足对当前转换中未定义的实体的外部引用。所有这样的翻译器输出被收集到程序映像中,该程序映像包含在其执行环境中执行所需的信息。(强调我的) [脚注]实现必须表现得好像发生了这些不同的阶段,尽管实际上不同的阶段可能会折叠在一起。 在编译的最后阶段发生指定的错误,通常称为链接。它基本上意味着你将一堆实现文件编译成目标文件或库,现在你想让它们一起工作。 假设你定义的符号a在a.cpp。现在,b.cpp 宣布该符号并使用它。在链接之前,它只是假设该符号已在某处定义,但它还不关心在哪里。链接阶段负责查找符号并将其正确链接到b.cpp(实际上是与使用它的对象或库)。 如果您使用的是Microsoft Visual Studio,您将看到项目生成.lib文件。它们包含导出符号表和导入符号表。导入的符号将根据您链接的库进行解析,并为使用该符号的库.lib(如果有)提供导出的符号。 其他编译器/平台也存在类似的机制。 常见的错误信息error LNK2001,error LNK1120,error LNK2019对于微软的Visual Studio和undefined reference to 符号名称为GCC。 代码: struct X { virtual void foo(); }; struct Y : X { void foo() {} }; struct A { virtual ~A() = 0; }; struct B: