title: Linking error: undefined reference to `vtable for XXX`
body: <p>There is some linking error here. I looked for that online, yet still I couldn't find the problem. How can I fix it?</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Here is the code!
  All classes are in a same file for a pilot program.</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;utility&gt;
  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-&gt;get_begin();
              unsigned long e1 = this-&gt;get_end();
              unsigned long b2 = interval-&gt;get_begin();
              unsigned long e2 = interval-&gt;get_end();
              if (b1 == b2 &amp;&amp; e1 == e2)
                      return true;
              return false;
          }
  
          virtual bool is_within(Interval *interval) {
              unsigned long b1 = this-&gt;get_begin();
              unsigned long e1 = this-&gt;get_end();
              unsigned long b2 = interval-&gt;get_begin();
              unsigned long e2 = interval-&gt;get_end();
              if (b1 &gt;= b2 &amp;&amp; e1 &lt;= e2)
                  return true;
              return false;
          }
  
          virtual bool contains(Interval *interval) {    // Examine whether this interval contains another interval
              unsigned long b1 = this-&gt;get_begin();
              unsigned long e1 = this-&gt;get_end();
              unsigned long b2 = interval-&gt;get_begin();
              unsigned long e2 = interval-&gt;get_end();
              if (b1 &lt;= b2 &amp;&amp; e1 &gt;= e2)
                  return true;
              return false;
          }
  
          virtual bool is_empty() {
              return (get_end()&lt;get_begin())?true:false;
          }
  
          virtual bool is_intersect(Interval *interval) {
              unsigned long b1 = this-&gt;get_begin();
              unsigned long e1 = this-&gt;get_end();
              unsigned long b2 = interval-&gt;get_begin();
              unsigned long e2 = interval-&gt;get_end();
  
              if (b1&gt;e2)
                  return false;
              if (b2&gt;e1)
                  return false;
              return true;
          }
  
          virtual void print()
          {
              cout &lt;&lt; '('&lt;&lt;get_begin() &lt;&lt; ',' &lt;&lt; get_end() &lt;&lt; ")\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-&gt;get_begin();
          unsigned long end2 = interval-&gt;get_end();
          if (end &lt; begin2 || begin &gt; end2) {
              return new IntInterval(1, 0);
          }
          return new IntInterval((begin&gt;begin2)?begin:begin2, (end&lt;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", &amp;ip1, &amp;ip2, &amp;ip3, &amp;ip4);
              _begin = (ip1 &lt;&lt; 24) + (ip2 &lt;&lt; 16) + (ip3 &lt;&lt; 8) + ip4;
  
              ip1 = 0; ip2 = 0; ip3 = 0; ip4 = 0;
              sscanf(end.c_str(), "%u.%u.%u.%u", &amp;ip1, &amp;ip2, &amp;ip3, &amp;ip4);
              _end = (ip1 &lt;&lt; 24) + (ip2 &lt;&lt; 16) + (ip3 &lt;&lt; 8) + ip4;
  
              if ((_begin &gt; _end) ||  (_end &gt; MAX_IP_RANGE)){
                  cout&lt;&lt;"ERROR: The IP INTERVAL IS WRONG The range is "&lt;&lt;begin&lt;&lt;"-"&lt;&lt;end&lt;&lt;endl;
                  exit(0);
              }
          }
          return new IntInterval(_begin, _end);
      }
  
      bool compFunc (Interval * i, Interval * j) {
          return (i-&gt;get_begin() &lt; j-&gt;get_begin());
      }
  
      int main () {
  
          vector &lt;vector&lt;pair&lt;string, string&gt; &gt; &gt; nets;
  
          vector&lt;pair&lt;string, string&gt; &gt; x;
          vector&lt;pair&lt;string, string&gt; &gt; 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 &lt;IntInterval *&gt; _nets;
          for (int i=0; i&lt;(int)nets.size(); i++)
              for(int j=0; j&lt;(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()&gt;1)
              for (vector&lt;IntInterval *&gt;::iterator it = _nets.begin()+1; it &lt; _nets.end(); ) {
                  if ((*it)-&gt;get_begin()-1 == (*(it-1))-&gt;get_end()) {
                      (*(it-1))-&gt;set_end((*it)-&gt;get_end());
                      _nets.erase(it);
                  }
                  else if ((*it)-&gt;get_begin()-1 &lt;  (*(it-1))-&gt;get_end()) {
                      it++;
                      cout&lt;&lt;"ERROR: Network address overlapping!"&lt;&lt;endl;
                  }
                  else
                      it++;
              }
  
          for (int i=0; i&lt;(int)_nets.size(); i++)
              cout &lt;&lt; _nets[i]-&gt;get_begin() &lt;&lt; "  " &lt;&lt; _nets[i]-&gt;get_end() &lt;&lt; endl;
  
        return 0;
      }
  </code></pre>