[Bug]C++ XXX:undefined reference to "xxx"

时间:2023-03-09 09:02:26
[Bug]C++ XXX:undefined reference to "xxx"

昨天写了个广义表,写完后用clang++编译,结果给我报了一个这样的错

tanglizi@archlinux ~/Code/cpp/DS/genlist $ clang++ main.cpp genlist.cpp -o main

/tmp/main-9e993f.o: In function `GenList<long>::GenList(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
main.cpp:(.text._ZN7GenListIlEC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN7GenListIlEC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x19): undefined reference to `GenList<long>::update(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
clang-5.0: error: linker command failed with exit code 1 (use -v to see invocation)

可以看出是连接器找不到函数的实现

这就很难受了,明明是常见的类,咋就编译不过

这是我的文件(简略写了)

// main.cpp
#include "genlist.h"
#include <string>
using namespace std; int main(void){
GenList<long> list(string("(1, 2, (3, 4), ())")); //关键在这,连接器找不到构造函数的实现 return 0;
}
// genlist.h
#ifndef _GENLIST_H_
#define _GENLIST_H_ #include "genlistnode.h"
#include <iostream>
#include <string>
using namespace std; template <class T>
class GenList{
public:
GenList(const string &input){update(input)}; //看这里
...
private:
...
}; #endif // _GENLIST_H_
// genlist.cpp
#include "genlist.h" template <class T>
void GenList<T>::update(const string &input){ // 实现在这里
if (input[0]=='('){
int idx=1;
head=createGenList(input, idx);
}else
throw "Expresion Error!";
}

该实现的都实现了,就是编译不过

最后发现当我把模板去掉后,就可以编译通过了

这是为啥?

因为编译器在编译的时候,按需要把模板类换成一般类来编译

然而g++不允许把模板类定义和模板类方法实现分离编译,最后就是连接器报错undefined reference

解决方法就是将模板类和方法实现放在同一个头文件里编译

好气