web-dev-qa-db-fra.com

Erreur de liaison: référence non définie à `vtable for XXX`

Il y a une erreur de liaison ici. J'ai cherché cela en ligne, mais je n'ai toujours pas trouvé le problème. Comment puis-je le réparer?

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

Voici le code! Toutes les classes sont dans un même fichier pour un programme pilote.

#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;
    }
19
Amir

Vous n'avez jamais fourni d'implémentation pour virtual ~Interval(); et plusieurs autres fonctions. Vous devez fournir une implémentation pour toutes les fonctions virtuelles non pures que vous déclarez. En particulier, G ++ émet la vtable avec l'implémentation de la première fonction non en ligne déclarée dans une classe. Omettre son implémentation signifie que vous n'aurez pas de table virtuelle et que vous ne pourrez donc pas construire la classe (d'où ces erreurs).

En bref, définissez chaque fonction que vous déclarez, à l'exception des purs virtuels. Il y a certains cas où il est justifié de laisser de côté la définition d'une fonction déclarée, mais ils sont très rares.

34
bdonlan

J'ai eu le même problème. Je fusionnais mon code avec des modifications en amont et j'ai choisi ma modification par rapport à la modification apparemment identique d'un autre ingénieur dans le fichier d'en-tête. Il s'est avéré qu'ils avaient changé la constance de la méthode et je ne l'avais pas remarqué, et vous obtiendrez cette erreur pour la raison @bdonian dit.

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

et les leurs:

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

Lors de la fusion, j'ai choisi la première version, mais l'implémentation en avait la seconde, ce qui a amené le compilateur à supposer qu'il y a une surcharge de foo () qui n'est pas définie, et donc l'erreur.

1
scorpiodawg