c++ undefined reference to vtable

蹲街弑〆低调 提交于 2020-01-18 16:48:08

问题


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.


回答1:


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




回答2:


I Just encountered the same problem, but my problem was that I had not written the destructor codein 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() {}



回答3:


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).




回答4:


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;
}

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.




回答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.




回答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.



来源:https://stackoverflow.com/questions/4272432/c-undefined-reference-to-vtable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!