C++中undifined reference to xxx问题

[1]中有这样一份代码

#include 
using namespace std;
class Base
{
public:
    Base();
    void f1();//member function
    virtual void f2();//virtual function
    virtual void f3()=0;//pure virtual function
    virtual ~Base();//virtual destructor function
};
class Derive:public Base
{
public:
    Derive();
    void f1();
    void f2();
    void f3();
    virtual ~Derive();
};
int main () {
    Derive d;
    return 0;
}

运行时,出现如下错误:

undefined reference to Derive::Derive()
undefined reference to Derive::~Derive()

其实这份代码中有2处错误

  1. 显式构造函数需要加空函数体(null bodies)

  2. base类的虚函数也需要加函数体

报错的直接原因则是:找不到Derive类构造、析构函数的定义。因为没有定义、只有申明的函数是无法使用的。

简单起见,我们Derive构造析构函数加上花括号(空函数体)
Derive(){};

接着运行出现:

C++中undifined reference to xxx问题_第1张图片

现在找不到Base构造、析构函数的实现,还找不到虚函数表:
undefined reference to vtable for Derive

找不到vtable问题便是[2]中提到的

more obscure messages from the Gnu C++ compiler - or rather from the loader

解决方法是给Base中虚函数f2()也加上函数体。而由于Derive继承之后的f2仍然是虚函数,所以Derive::f2()也需要加上花括号。

这是因为链接器linker需要将虚函数表vtable 放入某个object file,但是linker无法找到正确的object文件[3]。所以虚函数要有定义

而成员函数f1()即时没有定义,在编译过程中也不会报错。当然你要强行调用这个没定义的函数也会同样报错。

最后总结一下:

  1. 显示申明构造函数、析构函数一定要有定义

  2. C++类继承过程中父类的普通成员函数可以没定义。但是虚函数一定要有定义

最终版的代码:

class Base
{
public:
    Base(){};
    void f1();//member function
    virtual void f2(){};//virtual function
    virtual void f3()=0;//pure virtual function
    virtual ~Base(){};//virtual destructor function
};
class Derive:public Base
{
public:
    Derive(){};
    void f1();
    void f2(){};
    void f3(){};
    virtual ~Derive(){};
};

Reference

你可能感兴趣的:(c++)