C++项目报错Undefined symbols for architecture x86_64

用C++ OOP写数据结构的时候,运行的时候就提示

Undefined symbols for architecture x86_64:
  "AList<int>::AList(int)", referenced from:
      _main in main.cpp.o
ld: symbol(s) not found for architecture x86_64

部分代码如下(详细代码可以跳转到 GitHub仓库 进行查看)

  • main.cpp内容如下:

    #include <iostream>
    #include "utils/ArrayList.h"
    
    int main() {
      auto *list = new AList<int>(10);
      list->append(1);
      cout << list->toString();
      return 0;
    }
  • utils/ArrayList.h部分内容如下:

    #include "List.h"
    #include <iostream>
    using namespace std;
    
    const int DefaultSize = 10;
    
    template<typename E>
    class AList : public List<E> {
    public:
      explicit AList(int size);
    };
  • utils/ArrayList.cpp部分内容如下:

    #include "ArrayList.h"
    template<typename E>
    AList<E>::AList(int size) {
      // 实现
    }

我也参照 StackOverflow 上的帖子进行了修改,但是所描述的内容就是:函数或方法声明需要添加在.h文件中,而不是.cpp文件中

请问这个应该怎么解决?谢谢各位!

测试了一下,将实现代码放到 .h 文件中或者加上一句 #include "ArrayList.cpp" 就没问题了

阅读 6.9k
1 个回答

简短的回答:用这个命令编译就行了 gcc main.cpp ArrayList.cpp -o program


原因对程序编译过程有个基本了解就懂了。

从源码到二进制需要经过一系列步骤(别杠我):

  1. 预处理,#define 这些
  2. 编译器内部对源码文本进行语法、语义分析
  3. 从分析结果翻译成汇编或其他中间形式(比如LLVM IR)
  4. 汇编成目标文件(.o或.obj),包含符号、导入导出、重定位等信息
  5. 把多个目标文件、静态库(.a或.lib)、动态库(.dll/.so)链接、组装成可执行文件(.exe或.dll/.so)

你的代码里,main.cpp 引用了 ArrayList 相关函数,只#include了声明,这个情况下编译器认为这些函数在其他地方定义,不需要知道定义编译器也可以完成1-4步。

但是在第5步,你想要编译出一个可执行文件,编译器(准确说是链接器负责干这件事)必须找到 ArrayList 相关函数到底定义在哪儿,不然工作就没法干了。这一步必须告诉链接器所有要引用的符号应该在哪儿去找,也就是gcc -lxxx后面 -lxxx 这个参数干的事,告诉链接器去 xxx 这个库里找我引用的外部符号。

你的案例中,ArrayList 的相关函数定义显然不能在编译器默认链接的库里找到,毕竟这是你自己的东西。所以就必须告诉编译器,请把 main.cpp 和 ArrayList.cpp 一起处理,链接的时候记得到 ArrayList.cpp 里找我引用的函数。

于是编译命令就成了上面的样子。当然也可以用另一种形式:

gcc mian.cpp -c -o main.o
gcc ArrayList.cpp -c -o ArrayList.o
gcc main.o ArrayList.o -o program

这样就是分别编译好 main.o 和 ArrayList.o 两个目标文件,然后告诉 gcc 麻烦把这两个目标文件给链接成 program 可执行文件。

顺便一提 gcc 命令其实是一个驱动,真正编译和链接分别是 cc1plusld 干的。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题