问题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文件。

解决方法

  1. 在项目左侧Projects中找到当前工程,在工程名上右键,选择Properties…。

    如果左侧Workspace下为空,说明没有建立工程。请在菜单中File - New - Project…建立工程,并跳到第4步。

  2. 选择Build targets标签页,查看Debug(或者Default)下的Build target files,查看是否所有文件都被选中。

    如果文件都选中了,那么不是这种情况的问题。

  3. 如果有文件没有被选中的话,将其选中,然后点OK。

  4. 下一次在File - New - File的时候,出现下图的窗口时,记得全部勾上。

第三种情况:函数的声明和定义不匹配

问题分析

在这个例子中,Foo是一个类型,我们对其重载了<<运算符。

1
ostream& operator<<(ostream &os,const Foo &x);

但是我们在定义<<运算符重载的时候,写成了如下形式:

1
2
3
4
5
ostream& operator<<(ostream &os, Foo &x)	//这里缺了const
{
//TODO
return os;
}

函数的声明和定义并不匹配,因此会报错。而且这种报错只会出现在,函数已经声明,但没有其定义或者定义不匹配的时候。

如果没有声明函数的话,报错将会是No match for xxx。如果该函数是某个类的友元函数的话,会报XX is private错误。

解决方法

如果没有定义的话,定义函数。如果已经定义了函数的话,将函数的声明和定义保持一致。

第四种情况:类模板的函数声明和定义分离

问题分析

在之前的面向对象程序设计中,一般习惯是将类的成员和成员函数的声明写在.h文件里,而将各个成员函数的实现、和静态成员变量的初始化写在对应cpp文件里面。而当引入类模板之后,如果继续这样操作的话,将会报错。

解决方法

将该类的声明,与成员函数的实现、静态变量的初始化写在同一个文件(一般是头文件)里面。

第五中情况:类模板的友元的声明

问题分析

当有如下代码时,将会报错

1
2
3
4
5
6
7
8
9
10
11
12
template <class T>
class Foo
{
friend ostream& operator<<(ostream &os,const Foo&x);

T a;

public:
Foo(const T &a);
~Foo();
Foo(const Foo& other);
};

这是因为声明友元的时候没有声明其为函数模板。

解决方法

声明友元函数的时候,也需要声明其为函数模板。

方法1

1
2
3
4
5
6
7
8
9
10
11
template <class T>
class Foo
{
template <class Type>
friend ostream& operator<<(ostream &os,const Foo<Type>&x);
T a;
public:
Foo(const T &a);
~Foo();
Foo(const Foo& other);
};

如果将上面的Type改成T,那么在VS上正常编译,在G++(Code Blocks)上无法编译通过,报错如下:

方法2(教材上的示例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <class T> class Foo;

template <class T> ostream& operator<<(ostream &os,const Foo<T>&x);

template <class T>
class Foo
{
friend ostream& operator<< <>(ostream &os,const Foo&x); //注意这里的<>
T a;
public:
Foo(const T &a);
~Foo();
Foo(const Foo& other);
};

总结

  • undefined reference to 'XX'这种报错会出现在,函数已经声明,而且调用时参数与声明的一致,但是没有定义或者声明与定义(实现)不匹配的时候。
  • 如果没有声明函数或者调用时参数与声明不一样的话,报错将会是No match for xxx。如果该函数是某个类的友元函数的话,还会报XX is private错误。