'c++ undefined reference to vtable

I'm learning C++. I'm trying to do an exercise where I define several implementations of a pure virtual class with a single function. I'm having trouble linking the class that uses these implementations.

==> BasicMath.h <==
#ifndef BASIC_MATH_H
#define BASIC_MATH_H

#include<string>
#include<vector>    

class BasicMath { };


#endif // BASIC_MATH_H

==> Operation.h <==

#ifndef OPERATION
#define OPERATION

#include<string>
#include<vector>    

class Operation {
 public:
  virtual void perform(std::vector<std::string> vec) = 0;
};


#endif // OPERATION

==> Sum.h <==
#ifndef SUM_H
#define SUM_H

#include "Operation.h"

class Sum: public Operation {
 public:
  void perform(std::vector<std::string> vec);
};

#endif // SUM_H

==> BasicMath.cpp <==
#ifndef BASIC_MATH_C
#define BASIC_MATH_C

#include <string>
#include <vector>
#include <iostream>
#include "BasicMath.h"
#include "Sum.h"

int main(int argc, char* argv[]) {
  Sum op;
}

#endif // BASIC_MATH_C

==> Sum.cpp <==
#ifndef SUM_C
#define SUM_C

#include <vector>
#include <string>
#include <iostream>
#include "Sum.h"

void Sum::perform(std::vector<std::string> vec) {
    using namespace std;
    int total = 0;
    cout << "Total: " << total << "\n";
};

#endif // SUM_C

Compilation:

$ g++ -c Sum.cpp
$ g++ -o BasicMath BasicMath.cpp
/tmp/cc1VXjNl.o:BasicMath.cpp:(.text$_ZN3SumC1Ev[Sum::Sum()]+0x16): undefined reference to `vtable for Sum'
collect2: ld returned 1 exit status

I'm 95% sure I'm doing at least one foolish thing here - but my brain is refusing to tell me what.

I have see this question but have not managed to fix my issue.



Solution 1:[1]

You're not including the Sum.o object file on your compile&link line (second g++ use).

Solution 2:[2]

I Just encountered the same problem, but my problem was that I had not written the destructor code in my .cpp file.

class.h:

class MyClass {
public:
    MyClass();
    virtual ~MyClass();
};

class.cpp:

MyClass::MyClass() {}

It just gave me the vtable error message, and implementing the (empty) destructor solved the problem.

[Edit] Thus, the corrected class file looks like this:

MyClass::MyClass() {}
MyClass::~MyClass() {}

Solution 3:[3]

That error also happens if you forget the = 0 for pure virtual functions

Error:

class Base {
    public:
        virtual void f();
};

class Derived : public Base {
    public:
        virtual void f() {}
};

int main() {
    Derived d;
    Base *b = &d;
    (void)b;
}

No error:

class Base {
    public:
        virtual void f() = 0;
};

This is because without the = 0, C++ does not know that it is a pure virtual function, treats it as a declaration, expecting a later definition.

Tested on g++ 5.2.1.

Tested as of GCC 11.2.0, the error message changed to:

undefined reference to `typeinfo for Base'

command:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp

Solution 4:[4]

A couple of people have already pointed out the solution to the problem you've seen.

I'll add something rather different. You only need header guards in your headers. You've included them in your source files as well, where they really don't make sense. For example, I've commented out the lines you really don't need (or even want) in sum.cpp:

//#ifndef SUM_C
//#define SUM_C
//
#include <vector>
#include <string>
#include <iostream>
#include "Sum.h"

void Sum::perform(std::vector<std::string> vec) {
    using namespace std;
    int total = 0;
    cout << "Total: " << total << "\n";
};

//#endif // SUM_C

Just FWIW, instead of perform, I'd use operator():

class Operation {
 public:
  virtual void operator()(std::vector<std::string> vec) = 0;
};

and (obviously) that's also what you'd overload for Sum. To use it, instead of something like:

Sum op;
op.perform();

You'd use something like:

Sum op;
op();

This is particularly convenient when you combine your class with others (e.g., those in the standard library) that invoke operations like functions, whether they're really functions, or "functors" (classes like this, that overload operator() so syntactically they can be used almost like functions).

Solution 5:[5]

I normally encounter this error when I accidentally forget the =0 at the end of one of my functions in a pure virtual class.

Solution 6:[6]

You're just compiling BasicMath.cpp without Sum.cpp - your linker has no idea about Sum.cpp. You'll need to compile them both together, i.e. Sum.cpp BasicMath.cpp in one go, or you can compile the .cpp files independently and then create the executable by calling g++ with both .o files.

Solution 7:[7]

I have met the problem same as yours , and I solved this problem by adding three lines in the CMakeLists.txt , that is:

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Edward Strange
Solution 2 Alexis Wilke
Solution 3
Solution 4 Jerry Coffin
Solution 5 doron
Solution 6 EboMike
Solution 7 Zahra