Undefined reference to vtable

前端 未结 16 2116
死守一世寂寞
死守一世寂寞 2020-11-21 20:30

When building my C++ program, I\'m getting the error message

undefined reference to \'vtable...

What is the cause of this probl

相关标签:
16条回答
  • 2020-11-21 21:29

    The GCC FAQ has an entry on it:

    The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]/7.

    Therefore, you need to provide a definition for the virtual destructor:

    virtual ~CDasherModule()
    { };
    
    0 讨论(0)
  • There is lot of speculation going on in various answers here. I'll below give a fairly minimal code that reproduces this error and explain why it is occuring.

    Fairly Minimal Code to Reproduce This Error

    IBase.hpp

    #pragma once
    
    class IBase {
        public:
            virtual void action() = 0;
    };
    

    Derived.hpp

    #pragma once
    
    #include "IBase.hpp"
    
    class Derived : public IBase {
        public:
            Derived(int a);
            void action() override;
    };
    

    Derived.cpp

    #include "Derived.hpp"
    Derived::Derived(int a) { }
    void Derived::action() {}
    

    myclass.cpp

    #include <memory>
    #include "Derived.hpp"
    
    class MyClass {
    
        public:
            MyClass(std::shared_ptr<Derived> newInstance) : instance(newInstance) {
    
            }
    
            void doSomething() {
                instance->action();
            }
    
        private:
            std::shared_ptr<Derived> instance;
    };
    
    int main(int argc, char** argv) {
        Derived myInstance(5);
        MyClass c(std::make_shared<Derived>(myInstance));
        c.doSomething();
        return 0;
    }
    

    You can compile this using GCC like this:

    g++ -std=c++11 -o a.out myclass.cpp Derived.cpp
    

    You can now reproduce the error by removing = 0 in IBase.hpp. I get this error:

    ~/.../catkin_ws$ g++ -std=c++11 -o /tmp/m.out /tmp/myclass.cpp /tmp/Derived.cpp
    /tmp/cclLscB9.o: In function `IBase::IBase(IBase const&)':
    myclass.cpp:(.text._ZN5IBaseC2ERKS_[_ZN5IBaseC5ERKS_]+0x13): undefined reference to `vtable for IBase'
    /tmp/cc8Smvhm.o: In function `IBase::IBase()':
    Derived.cpp:(.text._ZN5IBaseC2Ev[_ZN5IBaseC5Ev]+0xf): undefined reference to `vtable for IBase'
    /tmp/cc8Smvhm.o:(.rodata._ZTI7Derived[_ZTI7Derived]+0x10): undefined reference to `typeinfo for IBase'
    collect2: error: ld returned 1 exit status
    

    Explanation

    Notice that above code does not require any virtual destructors, constructors or any other extra files for compile to be successful (although you should have them).

    The way to understand this error is as follows: Linker is looking for constructor of IBase. This it will need it for the constructor of Derived. However as Derived overrides methods from IBase, it has vtable attached to it that will reference IBase. When linker says "undefined reference to vtable for IBase" it basically means that Derived has vtable reference to IBase but it can't find any compiled object code of IBase to look up to. So the bottom line is that class IBase has declarations without implementations. This means a method in IBase is declared as virtual but we forgot to mark it as pure virtual OR provide its definition.

    Parting Tip

    If all else fails then one way to debug this error is to build minimal program that does compile and then keep changing it so it gets to the state you want. In between, keep compiling to see when it starts to fail.

    Note on ROS and Catkin build system

    If you were compiling above set of classes in ROS using catkin build system then you will need following lines in CMakeLists.txt:

    add_executable(myclass src/myclass.cpp src/Derived.cpp)
    add_dependencies(myclass theseus_myclass_cpp)
    target_link_libraries(myclass ${catkin_LIBRARIES})
    

    The first line basically says that we want to make an executable named myclass and the code to build this can be found files that follows. One of these files should have main(). Notice that you don't have to specify .hpp files anywhere in CMakeLists.txt. Also you don't have to specify Derived.cpp as library.

    0 讨论(0)
  • 2020-11-21 21:32

    The GNU C++ compiler has to make a decision where to put the vtable in case you have the definition of the virtual functions of an object spread across multiple compilations units (e.g. some of the objects virtual functions definitions are in a .cpp file others in another .cpp file, and so on).

    The compiler chooses to put the vtable in the same place as where the first declared virtual function is defined.

    Now if you for some reason forgot to provide a definition for that first virtual function declared in the object (or mistakenly forgot to add the compiled object at linking phase), you will get this error.

    As a side effect, please note that only for this particular virtual function you won't get the traditional linker error like you are missing function foo.

    0 讨论(0)
  • 2020-11-21 21:34

    So I was using Qt with Windows XP and MinGW compiler and this thing was driving me crazy.

    Basically the moc_xxx.cpp was generated empty even when I was added

    Q_OBJECT

    Deleting everything making functions virtual, explicit and whatever you guess doesn't worked. Finally I started removing line by line and it turned out that I had

    #ifdef something
    

    Around the file. Even when the #ifdef was true moc file was not generated.

    So removing all #ifdefs fixed the problem.

    This thing was not happening with Windows and VS 2013.

    0 讨论(0)
提交回复
热议问题