链接错误:未定义的引用“XXX的vtable”

时间:2021-03-20 22:52:09

There is some linking error here. I looked for that online, yet still I couldn't find the problem. How can I fix it?

这里有一些链接错误。我在网上找过,但还是找不到问题。我怎样才能修好它?

g++ test.cpp -o test
/tmp/ccDfCj4N.o: In function `Interval::Interval()':
test.cpp:(.text._ZN8IntervalC2Ev[Interval::Interval()]+0x9): undefined reference to     `vtable for Interval'
/tmp/ccDfCj4N.o: In function `IntInterval::~IntInterval()':
test.cpp:(.text._ZN11IntIntervalD0Ev[IntInterval::~IntInterval()]+0x1d): undefined     reference to `Interval::~Interval()'
/tmp/ccDfCj4N.o: In function `IntInterval::~IntInterval()':
test.cpp:(.text._ZN11IntIntervalD1Ev[IntInterval::~IntInterval()]+0x1d): undefined     reference to `Interval::~Interval()'
/tmp/ccDfCj4N.o:(.rodata._ZTI11IntInterval[typeinfo for IntInterval]+0x10): undefined     reference to `typeinfo for Interval'
collect2: ld returned 1 exit status

Here is the code! All classes are in a same file for a pilot program.

这是代码!所有的类都在一个相同的文件中进行试点。

#include <iostream>
#include <vector>
#include <utility>
using namespace std;

#define MAX_IP_RANGE    4294967295

class Interval {

    public:
        virtual Interval * interval_copy() = 0;
        virtual unsigned long get_begin() = 0;
        virtual unsigned long get_end() = 0;
        virtual unsigned long get_length() = 0;
        virtual Interval*     get_intersect(Interval *interval) = 0;   // Examine whether two intervals have intersection
        virtual Interval*     copy() = 0;
        virtual ~Interval();
        virtual bool is_equal(Interval *interval) {
            unsigned long b1 = this->get_begin();
            unsigned long e1 = this->get_end();
            unsigned long b2 = interval->get_begin();
            unsigned long e2 = interval->get_end();
            if (b1 == b2 && e1 == e2)
                    return true;
            return false;
        }

        virtual bool is_within(Interval *interval) {
            unsigned long b1 = this->get_begin();
            unsigned long e1 = this->get_end();
            unsigned long b2 = interval->get_begin();
            unsigned long e2 = interval->get_end();
            if (b1 >= b2 && e1 <= e2)
                return true;
            return false;
        }

        virtual bool contains(Interval *interval) {    // Examine whether this interval contains another interval
            unsigned long b1 = this->get_begin();
            unsigned long e1 = this->get_end();
            unsigned long b2 = interval->get_begin();
            unsigned long e2 = interval->get_end();
            if (b1 <= b2 && e1 >= e2)
                return true;
            return false;
        }

        virtual bool is_empty() {
            return (get_end()<get_begin())?true:false;
        }

        virtual bool is_intersect(Interval *interval) {
            unsigned long b1 = this->get_begin();
            unsigned long e1 = this->get_end();
            unsigned long b2 = interval->get_begin();
            unsigned long e2 = interval->get_end();

            if (b1>e2)
                return false;
            if (b2>e1)
                return false;
            return true;
        }

        virtual void print()
        {
            cout << '('<<get_begin() << ',' << get_end() << ")\n";
        }
};


class IntInterval : public Interval {
    private:
        unsigned long begin;
        unsigned long end;
        IntInterval();

    public:
        virtual Interval * interval_copy() {
            return new IntInterval(begin, end);
        }

        IntInterval(unsigned long a, unsigned long b): begin (a), end  (b)
        {}

        void set_value(unsigned long a, unsigned long b) {
            begin = a;
            end = b;
        }

        void set_begin(unsigned long a) {
            begin = a;
        }

        void set_end(unsigned long b) {
            end = b;
        }

        virtual Interval* copy()
        {
            Interval *new_interval = new IntInterval(begin, end);
            return new_interval;
        }

        virtual unsigned long get_begin() {
            return begin;
        }

        virtual unsigned long get_length() {
            return end-begin+1;
        }

        virtual unsigned long  get_end() {
            return end;
        }

        virtual Interval* get_intersect(Interval *interval);   // Get the intersect part of two intervals
        virtual ~IntInterval() {};
    };

    Interval* IntInterval::get_intersect(Interval *interval) {
        unsigned long begin2 = interval->get_begin();
        unsigned long end2 = interval->get_end();
        if (end < begin2 || begin > end2) {
            return new IntInterval(1, 0);
        }
        return new IntInterval((begin>begin2)?begin:begin2, (end<end2)?end:end2);
    }


    IntInterval * parse_ip(const char * _str) {
        unsigned long  _begin=0;
        unsigned long  _end=0;
        string input(_str);
        if (input.find('-') != string::npos){
            string begin = input.substr(0, input.find('-'));
            string end = input.substr(input.find('-')+1);

            unsigned  int ip1 = 0, ip2 = 0;
            unsigned  int ip3 = 0, ip4 = 0;
            sscanf(begin.c_str(), "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
            _begin = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;

            ip1 = 0; ip2 = 0; ip3 = 0; ip4 = 0;
            sscanf(end.c_str(), "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
            _end = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;

            if ((_begin > _end) ||  (_end > MAX_IP_RANGE)){
                cout<<"ERROR: The IP INTERVAL IS WRONG The range is "<<begin<<"-"<<end<<endl;
                exit(0);
            }
        }
        return new IntInterval(_begin, _end);
    }

    bool compFunc (Interval * i, Interval * j) {
        return (i->get_begin() < j->get_begin());
    }

    int main () {

        vector <vector<pair<string, string> > > nets;

        vector<pair<string, string> > x;
        vector<pair<string, string> > y;

        x.push_back(make_pair("1.1.1.1", "3.0.0.0"));
        x.push_back(make_pair("10.2.5.3", "30.2.5.0"));
        x.push_back(make_pair("100.2.25.2", "130.2.25.2"));

        y.push_back(make_pair("41.0.2.2", "43.2.2.5"));
        y.push_back(make_pair("131.2.2.2", "135.5.5.2"));

        nets.push_back(x);
        nets.push_back(y);

        vector <IntInterval *> _nets;
        for (int i=0; i<(int)nets.size(); i++)
            for(int j=0; j<(int)nets[i].size(); j++) {
                string s = nets[i][j].first + '-' + nets[i][j].second;
                _nets.push_back(parse_ip(s.c_str()));
            }
        sort(_nets.begin(), _nets.end(), compFunc);

        if (_nets.size()>1)
            for (vector<IntInterval *>::iterator it = _nets.begin()+1; it < _nets.end(); ) {
                if ((*it)->get_begin()-1 == (*(it-1))->get_end()) {
                    (*(it-1))->set_end((*it)->get_end());
                    _nets.erase(it);
                }
                else if ((*it)->get_begin()-1 <  (*(it-1))->get_end()) {
                    it++;
                    cout<<"ERROR: Network address overlapping!"<<endl;
                }
                else
                    it++;
            }

        for (int i=0; i<(int)_nets.size(); i++)
            cout << _nets[i]->get_begin() << "  " << _nets[i]->get_end() << endl;

      return 0;
    }

3 个解决方案

#1


29  

You never provided an implementation for virtual ~Interval(); and several other functions. You must provide an implementation for all non-pure virtual functions you declare. In particular, G++ emits the vtable along with the implementation of the first-declared non-inline function in a class. Omitting its implementation means you won't have a vtable, and thus won't be able to construct the class (hence these errors).

您从未提供过虚拟~Interval()的实现;和其他几个功能。您必须为声明的所有非纯虚拟函数提供实现。特别是,在类中,g++会发出vtable,并实现第一个声明的非内联函数。省略它的实现意味着您不会有一个vtable,因此无法构造类(因此这些错误)。

In short, define every function you declare, except for pure virtuals. There are some cases where it's justified to leave out the definition for a declared function, but they are very rare.

简而言之,定义您声明的每个函数,除了纯虚拟。在某些情况下,为声明的函数保留定义是合理的,但它们非常罕见。

#2


1  

I had the same problem. I was merging my code with upstream changes and picked my change over another engineer's seemingly identical change in the header file. It just turned out that they had changed the constness of the method and I hadn't noticed, and you will get this error for the reason @bdonian says.

我遇到了同样的问题。我正在将我的代码与上游更改合并,并在头文件中选择了另一个工程师看起来相同的更改。结果是他们改变了方法的一致性,我没有注意到,你会得到这个错误的原因@bdonian说。

virtual void foo(Many params, As part, Of veryLong, Method signature);

and theirs:

和他们的:

virtual void foo(Many params, As part, Of veryLong, Method signature) const;

When merging I picked the first version, but the implementation had the second one, resulting in the compiler assuming there is an overload of foo() that is undefined, and hence the error.

在合并时,我选择了第一个版本,但是实现有第二个版本,导致编译器假设有一个未定义的foo()重载,因此出现了错误。

#3


-3  

In virtual classes never put undefined functions first. Move

在虚拟类中,永远不要把未定义的函数放在第一位。移动

IntInterval();

to after the first defined function:

在第一个定义的函数之后:

private:
    unsigned long begin;
    unsigned long end;

public:
    virtual Interval * interval_copy(){return new IntInterval(begin,end);}
    IntInterval(unsigned long a,unsigned long b): begin (a),
                                  end  (b)
    {}
private:
    IntInterval();
public:

It's because C++ glues the vtable to the first function. If you don't define it, the vtable will be undefined as well.

这是因为c++将vtable映射到第一个函数。如果您不定义它,那么vtable也将是未定义的。

As mentioned by other answers, you need to also define the destructor:

正如其他答案所提到的,您还需要定义析构函数:

public:
    virtual ~IntInterval()
    {
        // Destruction code
    }

#1


29  

You never provided an implementation for virtual ~Interval(); and several other functions. You must provide an implementation for all non-pure virtual functions you declare. In particular, G++ emits the vtable along with the implementation of the first-declared non-inline function in a class. Omitting its implementation means you won't have a vtable, and thus won't be able to construct the class (hence these errors).

您从未提供过虚拟~Interval()的实现;和其他几个功能。您必须为声明的所有非纯虚拟函数提供实现。特别是,在类中,g++会发出vtable,并实现第一个声明的非内联函数。省略它的实现意味着您不会有一个vtable,因此无法构造类(因此这些错误)。

In short, define every function you declare, except for pure virtuals. There are some cases where it's justified to leave out the definition for a declared function, but they are very rare.

简而言之,定义您声明的每个函数,除了纯虚拟。在某些情况下,为声明的函数保留定义是合理的,但它们非常罕见。

#2


1  

I had the same problem. I was merging my code with upstream changes and picked my change over another engineer's seemingly identical change in the header file. It just turned out that they had changed the constness of the method and I hadn't noticed, and you will get this error for the reason @bdonian says.

我遇到了同样的问题。我正在将我的代码与上游更改合并,并在头文件中选择了另一个工程师看起来相同的更改。结果是他们改变了方法的一致性,我没有注意到,你会得到这个错误的原因@bdonian说。

virtual void foo(Many params, As part, Of veryLong, Method signature);

and theirs:

和他们的:

virtual void foo(Many params, As part, Of veryLong, Method signature) const;

When merging I picked the first version, but the implementation had the second one, resulting in the compiler assuming there is an overload of foo() that is undefined, and hence the error.

在合并时,我选择了第一个版本,但是实现有第二个版本,导致编译器假设有一个未定义的foo()重载,因此出现了错误。

#3


-3  

In virtual classes never put undefined functions first. Move

在虚拟类中,永远不要把未定义的函数放在第一位。移动

IntInterval();

to after the first defined function:

在第一个定义的函数之后:

private:
    unsigned long begin;
    unsigned long end;

public:
    virtual Interval * interval_copy(){return new IntInterval(begin,end);}
    IntInterval(unsigned long a,unsigned long b): begin (a),
                                  end  (b)
    {}
private:
    IntInterval();
public:

It's because C++ glues the vtable to the first function. If you don't define it, the vtable will be undefined as well.

这是因为c++将vtable映射到第一个函数。如果您不定义它,那么vtable也将是未定义的。

As mentioned by other answers, you need to also define the destructor:

正如其他答案所提到的,您还需要定义析构函数:

public:
    virtual ~IntInterval()
    {
        // Destruction code
    }