问题undefined reference to 'XX'的解决方法
在G++(Code Blocks自带编译器)中,有时会报错undefined reference to 'XX'
。而在VS中相同问题的可能报错“无法解析的外部符号,xxxx,该符号在函数XX中被引用”。需要明确的是,这个问题属于链接错误,不是编译错误,因此核心思想是看函数是不是只声明了而没有定义,和函数内部的代码无关。具体原因有几种,下面将分别列举原因与解决方法。
第一种情况:没写main函数
问题分析
报错信息为:undefine reference to 'WinMain'
。
看到这个报错,只有一种情况,就是没写main
函数,找不到可执行程序的入口。
解决方法
在程序中写上main
函数即可。
第二种情况:工程文件配置错误
问题分析
这种情况可能会出现在Code Blocks中,一般不会出现在Visual Studio中。
程序代码由多个.cpp
文件和若干个.h
文件组成,编译时只编译了main
函数所在的cpp
文件,没有编译(或者链接)上报错中函数的定义所在的cpp
文件。
解决方法
在项目左侧Projects中找到当前工程,在工程名上右键,选择Properties…。
如果左侧Workspace下为空,说明没有建立工程。请在菜单中File - New - Project…建立工程,并跳到第4步。
选择Build targets标签页,查看Debug(或者Default)下的Build target files,查看是否所有文件都被选中。
如果文件都选中了,那么不是这种情况的问题。
如果有文件没有被选中的话,将其选中,然后点OK。
下一次在File - New - File的时候,出现下图的窗口时,记得全部勾上。
第三种情况:函数的声明和定义不匹配
问题分析
在这个例子中,Foo
是一个类型,我们对其重载了<<
运算符。
1 | ostream& operator<<(ostream &os,const Foo &x); |
但是我们在定义<<运算符重载的时候,写成了如下形式:
1 | ostream& operator<<(ostream &os, Foo &x) //这里缺了const |
函数的声明和定义并不匹配,因此会报错。而且这种报错只会出现在,函数已经声明,但没有其定义或者定义不匹配的时候。
如果没有声明函数的话,报错将会是No match for xxx
。如果该函数是某个类的友元函数的话,会报XX is private
错误。
解决方法
如果没有定义的话,定义函数。如果已经定义了函数的话,将函数的声明和定义保持一致。
第四种情况:类模板的函数声明和定义分离
问题分析
在之前的面向对象程序设计中,一般习惯是将类的成员和成员函数的声明写在.h
文件里,而将各个成员函数的实现、和静态成员变量的初始化写在对应cpp
文件里面。而当引入类模板之后,如果继续这样操作的话,将会报错。
解决方法
将该类的声明,与成员函数的实现、静态变量的初始化写在同一个文件(一般是头文件)里面。
第五中情况:类模板的友元的声明
问题分析
当有如下代码时,将会报错
1 | template <class T> |
这是因为声明友元的时候没有声明其为函数模板。
解决方法
声明友元函数的时候,也需要声明其为函数模板。
方法1
1 | template <class T> |
如果将上面的Type
改成T
,那么在VS上正常编译,在G++(Code Blocks)上无法编译通过,报错如下:
方法2(教材上的示例)
1 | template <class T> class Foo; |
总结
undefined reference to 'XX'
这种报错会出现在,函数已经声明,而且调用时参数与声明的一致,但是没有定义或者声明与定义(实现)不匹配的时候。- 如果没有声明函数或者调用时参数与声明不一样的话,报错将会是
No match for xxx
。如果该函数是某个类的友元函数的话,还会报XX is private
错误。