533

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

undefined reference to 'vtable...

What is the cause of this problem? How do I fix it?


It so happens that I'm getting the error for the following code (The class in question is CGameModule.) and I cannot for the life of me understand what the problem is. At first, I thought it was related to forgetting to give a virtual function a body, but as far as I understand, everything is all here. The inheritance chain is a little long, but here is the related source code. I'm not sure what other information I should provide.

Note: The constructor is where this error is happening, it'd seem.

My code:

class CGameModule : public CDasherModule {
 public:
  CGameModule(Dasher::CEventHandler *pEventHandler, CSettingsStore *pSettingsStore, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName)
  : CDasherModule(pEventHandler, pSettingsStore, iID, 0, szName)
  { 
      g_pLogger->Log("Inside game module constructor");   
      m_pInterface = pInterface; 
  }

  virtual ~CGameModule() {};

  std::string GetTypedTarget();

  std::string GetUntypedTarget();

  bool DecorateView(CDasherView *pView) {
      //g_pLogger->Log("Decorating the view");
      return false;
  }

  void SetDasherModel(CDasherModel *pModel) { m_pModel = pModel; }


  virtual void HandleEvent(Dasher::CEvent *pEvent); 

 private:



  CDasherNode *pLastTypedNode;


  CDasherNode *pNextTargetNode;


  std::string m_sTargetString;


  size_t m_stCurrentStringPos;


  CDasherModel *m_pModel;


  CDasherInterfaceBase *m_pInterface;
};

Inherits from...

class CDasherModule;
typedef std::vector<CDasherModule*>::size_type ModuleID_t;

/// \ingroup Core
/// @{
class CDasherModule : public Dasher::CDasherComponent {
 public:
  CDasherModule(Dasher::CEventHandler * pEventHandler, CSettingsStore * pSettingsStore, ModuleID_t iID, int iType, const char *szName);

  virtual ModuleID_t GetID();
  virtual void SetID(ModuleID_t);
  virtual int GetType();
  virtual const char *GetName();

  virtual bool GetSettings(SModuleSettings **pSettings, int *iCount) {
    return false;
  };

 private:
  ModuleID_t m_iID;
  int m_iType;
  const char *m_szName;
};

Which inherits from....

namespace Dasher {
  class CEvent;
  class CEventHandler;
  class CDasherComponent;
};

/// \ingroup Core
/// @{
class Dasher::CDasherComponent {
 public:
  CDasherComponent(Dasher::CEventHandler* pEventHandler, CSettingsStore* pSettingsStore);
  virtual ~CDasherComponent();

  void InsertEvent(Dasher::CEvent * pEvent);
  virtual void HandleEvent(Dasher::CEvent * pEvent) {};

  bool GetBoolParameter(int iParameter) const;
  void SetBoolParameter(int iParameter, bool bValue) const;

  long GetLongParameter(int iParameter) const;
  void SetLongParameter(int iParameter, long lValue) const;

  std::string GetStringParameter(int iParameter) const;
  void        SetStringParameter(int iParameter, const std::string & sValue) const;

  ParameterType   GetParameterType(int iParameter) const;
  std::string     GetParameterName(int iParameter) const;

 protected:
  Dasher::CEventHandler *m_pEventHandler;
  CSettingsStore *m_pSettingsStore;
};
/// @}


#endif
Raedwald
  • 46,613
  • 43
  • 151
  • 237
RyanG
  • 6,773
  • 5
  • 25
  • 24
  • 4
    I totally missed that the error message specifies a function. It happens to be the constructor, so I saw my class name and didn't make the connection. So, the constructor is throwing this. I'll add that detail to my original post. – RyanG Jun 17 '10 at 20:31
  • 4
    If you have not rebuilt your project files after making significant changes (e.g. `qmake -project` and then `qmake`) to generate a new `Makefile`, that is a likely source of the error when using Qt. – David C. Rankin Jul 13 '19 at 06:42
  • 4
    @DavidC.Rankin, another Qt related problem is that if the file with `Q_OBJECT` is copied externally, but not yet part of the .pro file, then though it compiles fine, it doesn't link. We have to add that `.h/.cpp` file into the .pro file to be able to `qmake`. – iammilind Jan 08 '20 at 05:00
  • When I commented some `.h` file, I accidentally typed a newline in `.pro` and the linker gave me this error –  May 25 '23 at 09:21

21 Answers21

533

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()
{ }
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
Alexandre Hamez
  • 7,725
  • 2
  • 28
  • 39
  • 25
    `nm -C CGameModule.o | grep CGameModule::` will list the methods that are defined, assuming your entire class implementation goes into the logical object file. You can compare that with what is defined as virtual to figure out what you missed. – Troy Daniels Sep 04 '14 at 20:49
  • 172
    FFS, why doesn’t the compiler check for that and print an error messsage? – Lenar Hoyt Oct 04 '14 at 22:13
  • 31
    Obviously, this can only be discovered by the linker, not the compiler. – Xoph Apr 12 '16 at 13:46
  • This was my problem too. The reason it was hard to find was because method signatures where too long extending well beyond view and there were too many such methods and that it was 2AM :). I kept believing I had all methods as pure abstract while one method hiding out. Ended up spending 4+ hours in trying to find out what else could be wrong... – Shital Shah May 10 '16 at 18:29
  • 3
    In my case we had abstract class that didn't have destructor implementation. I had to put the empty implementation ~MyClass(){} – Shefy Gur-ary Sep 11 '16 at 06:07
  • 2
    You can get an error like this when objects you are trying to link is missing in the archive (libxyz.a file): undefined reference to `vtable for objfilename' – Kemin Zhou Oct 20 '16 at 07:04
  • I had a virtual method in base class B, overridden in derived class D. I then made the method pure virtual in B and ran make. Make only recompiled class B, not class D. I got this error. `undefined reference to vtable for B D.o: undefined reference to typeinfo for B D.o: In function B::B() D.cpp: undefined reference to vtable for B` Compiling D.cpp fixed it. Diff between the old and new D.o is: OLD `U typeinfo for B U vtable for B` New `00000000 V typeinfo for B 00000000 V typeinfo name for B 00000000 V vtable for B` What is the error telling me exactly? – Will Aug 22 '17 at 09:19
  • 11
    It would be nice if the linker could produce a more friendly error message, perhaps specifying a hint of which method is not or is mis- defined. – David Elrod Nov 21 '18 at 21:28
  • 2
    Can also happen if you create a subclass of the abstract class and forget to implement something you overrode. – sudo Jun 21 '19 at 15:43
  • This solved my problem, but I had to make the destructor non-virtual. – UserX Sep 09 '21 at 19:20
  • The authors of this error message should be cursed with a lifetime of receiving unhelpful advice. – SF. Dec 12 '22 at 14:26
201

TL;DR - Explains why the vtable might be missing and how to fix it. The answer is long because it explains why the compiler might forget to create a vtable. (Editor)

What is a vtable?

It might be useful to know what the error message is talking about before trying to fix it. I'll start at a high level, then work down to some more details. That way people can skip ahead once they are comfortable with their understanding of vtables. …and there goes a bunch of people skipping ahead right now. :) For those sticking around:

A vtable is basically the most common implementation of polymorphism in C++. When vtables are used, every polymorphic class has a vtable somewhere in the program; you can think of it as a (hidden) static data member of the class. Every object of a polymorphic class is associated with the vtable for its most-derived class. By checking this association, the program can work its polymorphic magic. Important caveat: a vtable is an implementation detail. It is not mandated by the C++ standard, even though most (all?) C++ compilers use vtables to implement polymorphic behavior. The details I am presenting are either typical or reasonable approaches. Compilers are allowed to deviate from this!

Each polymorphic object has a (hidden) pointer to the vtable for the object's most-derived class (possibly multiple pointers, in the more complex cases). By looking at the pointer, the program can tell what the "real" type of an object is (except during construction, but let's skip that special case). For example, if an object of type A does not point to the vtable of A, then that object is actually a sub-object of something derived from A.

The name "vtable" comes from "virtual function table". It is a table that stores pointers to (virtual) functions. A compiler chooses its convention for how the table is laid out; a simple approach is to go through the virtual functions in the order they are declared within class definitions. When a virtual function is called, the program follows the object's pointer to a vtable, goes to the entry associated with the desired function, then uses the stored function pointer to invoke the correct function. There are various tricks for making this work, but I won't go into those here.

Where/when is a vtable generated?

A vtable is automatically generated (sometimes called "emitted") by the compiler. A compiler could emit a vtable in every translation unit that sees a polymorphic class definition, but that would usually be unnecessary overkill. An alternative (used by gcc, and probably by others) is to pick a single translation unit in which to place the vtable, similar to how you would pick a single source file in which to put a class' static data members. If this selection process fails to pick any translation units, then the vtable becomes an undefined reference. Hence the error, whose message is admittedly not particularly clear.

Similarly, if the selection process does pick a translation unit, but that object file is not provided to the linker, then the vtable becomes an undefined reference. Unfortunately, the error message can be even less clear in this case than in the case where the selection process failed. (Thanks to the answerers who mentioned this possibility. I probably would have forgotten it otherwise.)

The selection process used by gcc makes sense if we start with the tradition of devoting a (single) source file to each class that needs one for its implementation. It would be nice to emit the vtable when compiling that source file. Let's call that our goal. However, the selection process needs to work even if this tradition is not followed. So instead of looking for the implementation of the entire class, let's look for the implementation of a specific member of the class. If tradition is followed – and if that member is in fact implemented – then this achieves the goal.

The member selected by gcc (and potentially by other compilers) is the first non-inline virtual function that is not pure virtual. If you are part of the crowd that declares constructors and destructors before other member functions, then that destructor has a good chance of being selected. (You did remember to make the destructor virtual, right?) There are exceptions; I'd expect that the most common exceptions are when an inline definition is provided for the destructor and when the default destructor is requested (using "= default").

The astute might notice that a polymorphic class is allowed to provide inline definitions for all of its virtual functions. Doesn't that cause the selection process to fail? It does in older compilers. I've read that the latest compilers have addressed this situation, but I do not know relevant version numbers. I could try looking this up, but it's easier to either code around it or wait for the compiler to complain.

In summary, there are three key causes of the "undefined reference to vtable" error:

  1. A member function is missing its definition.
  2. An object file is not being linked.
  3. All virtual functions have inline definitions.

These causes are by themselves insufficient to cause the error on their own. Rather, these are what you would address to resolve the error. Do not expect that intentionally creating one of these situations will definitely produce this error; there are other requirements. Do expect that resolving these situations will resolve this error.

(OK, number 3 might have been sufficient when this question was asked.)

How to fix the error?

Welcome back people skipping ahead! :)

  1. Look at your class definition. Find the first non-inline virtual function that is not pure virtual (not "= 0") and whose definition you provide (not "= default").
    • If there is no such function, try modifying your class so there is one. (Error possibly resolved.)
    • See also the answer by Philip Thomas for a caveat.
  2. Find the definition for that function. If it is missing, add it! (Error possibly resolved.)
    • If the function definition is outside the class definition, then make sure the function definition uses a qualified name, as in ClassName::function_name.
  3. Check your link command. If it does not mention the object file with that function's definition, fix that! (Error possibly resolved.)
  4. Repeat steps 2 and 3 for each virtual function, then for each non-virtual function, until the error is resolved. If you're still stuck, repeat for each static data member.

Example
The details of what to do can vary, and sometimes branch off into separate questions (like What is an undefined reference/unresolved external symbol error and how do I fix it?). I will, though, provide an example of what to do in a specific case that might befuddle newer programmers.

Step 1 mentions modifying your class so that it has a function of a certain type. If the description of that function went over your head, you might be in the situation I intend to address. Keep in mind that this is a way to accomplish the goal; it is not the only way, and there easily could be better ways in your specific situation. Let's call your class A. Is your destructor declared (in your class definition) as either

virtual ~A() = default;

or

virtual ~A() {}

? If so, two steps will change your destructor into the type of function we want. First, change that line to

virtual ~A();

Second, put the following line in a source file that is part of your project (preferably the file with the class implementation, if you have one):

A::~A() {}

That makes your (virtual) destructor non-inline and not generated by the compiler. (Feel free to modify things to better match your code formatting style, such as adding a header comment to the function definition.)

JaMiT
  • 14,422
  • 4
  • 15
  • 31
  • 6
    Oh, bravo! For the very detailed and very well scoped explanation. – David C. Rankin Dec 06 '19 at 22:22
  • Had to scroll down way to far to read this. Have an upvote for the excellent explanation! – stackprotector Apr 29 '20 at 07:22
  • Thanks, moving the definition of constructor / destructor from header to CPP resolved the issue. – shaktisinghr Apr 14 '21 at 09:51
  • 1
    You are my hero. We have a fairly large codebase, and it's been a long time since I've had to add a new .cpp file. I was ripping my hair out until reading this, your Step 3, that I realized I had to add the .o file to the linker command. – livefree75 Feb 05 '22 at 00:35
  • Great answer. I forgot to put the functions as `ClassName::function_name` Fixing this resolved this issue for me. – zweack Mar 30 '22 at 11:58
  • @JaMit could you update your answer with zweack example please (missing ClassName:: in cpp)? I had exactly the same issue. It's one of those cases when you're staring at the issue and do not see it. So I think it worth mentioning it directly. – Roman Jun 09 '23 at 23:14
  • @Roman I might not understand your request. It looks to me that you are requesting that the answer state *"If the function definition is outside the class definition, then make sure the function definition uses a qualified name, as in `ClassName::function_name`."* However, the answer already states this. – JaMiT Jun 10 '23 at 01:59
187

For what it is worth, forgetting a body on a virtual destructor generates the following:

undefined reference to `vtable for CYourClass'.

I am adding a note because the error message is deceptive. (This was with gcc version 4.6.3.)

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
Dan
  • 1,887
  • 1
  • 11
  • 3
  • 29
    I had to explicitly put the body of my empty virtual destructor in the definition file (*.cc). Having it in the header still gave me the error. – PopcornKing Oct 29 '14 at 21:33
  • 6
    Note that once I added the virtual destructor to the implementation file, then gcc told me the actual error, which was a missing body on another function. – moodboom Jul 16 '15 at 23:47
  • 2
    @PopcornKing I saw the same issue. Even defining `~Destructor = default;` in the header file didn't help. Is there a documented bug filed against gcc? – R.D. Dec 08 '15 at 22:28
  • this may be a different issue, but my problem was just not having an implementation for a non-virtual destructor (was switching to unique / shared pointers and removed it from the source file, but didn't have an "implementation" in the header) – svenevs Apr 30 '16 at 07:57
  • this solved my problem, adding an empty {} body for the virtual destructor avoided the error. – Bogdan Ionitza Nov 19 '18 at 12:08
  • That was exactly it! Thanks. – Kostiantyn Ponomarenko Jan 28 '20 at 19:10
  • Not necessarily. I was getting this error even though my destructor had a body defined in the .h file. What solved the issue was turning every function pure virtual, but not the destructor. The destructor remained only virtual with the body defined in the .h file. – Thales Carl Sep 21 '21 at 14:35
  • Forgetting a body on "any" virtual function generates the error. Check the detailed answer below by @JaMiT. – Saber Nov 30 '22 at 20:07
70

So, I've figured out the issue and it was a combination of bad logic and not being totally familiar with the automake/autotools world. I was adding the correct files to my Makefile.am template, but I wasn't sure which step in our build process actually created the makefile itself. So, I was compiling with an old makefile that had no idea about my new files whatsoever.

Thanks for the responses and the link to the GCC FAQ. I will be sure to read that to avoid this problem occurring for a real reason.

RyanG
  • 6,773
  • 5
  • 25
  • 24
  • 60
    In brief : the .cpp just wasn't included in the build. The error message is really misleading. – Offirmo Mar 04 '13 at 14:47
  • 82
    For Qt users: you can get this same error if you forget to moc a header. – Chris Morlier Dec 19 '13 at 03:35
  • 9
    I think you should accept the answer of Alexandre Hamez though. People searching for this error would most likely need his solution instead of yours. – Tim Dec 24 '13 at 12:00
  • 17
    -1 This may be the solution to your problem, but it is not an answer to the original question. The correct answer is simply that you didn't provide a object file with the required symbols. Why you failed to provide them is another story. – Walter May 29 '14 at 08:22
  • 18
    @Walter: Actually this was the exact answer I was looking for. The others are obvious, and thus unhelpful. – Edgar Bonet Jun 10 '14 at 11:20
  • 5
    I agree with Edgar, you can expect to have such an error if you're missing a virtual function definition, but sometimes, the real answer is indeed the real answer. – bbill Jun 12 '14 at 18:16
  • A co-worker just had this problem. The base class had a virtual destructor. He did not define a destructor in the child class. – David Nov 21 '17 at 14:20
  • I had the same problem and everywhere I found that I need defined destructors. My problem was that I misstyped the file name when adding it to my makefile. I think the main problem with your answer is, that you only state your own solution. You should eventually rework it and say the whole process. :) – Matécsa Andrea Feb 13 '21 at 18:57
66

If you are using Qt, try rerunning qmake. If this error is in the widget's class, qmake might have failed to notice that the ui class vtable should be regenerated. This fixed the issue for me.

gluk47
  • 1,812
  • 20
  • 31
  • 4
    I just deleted whole folder with build it worked as well. – Tomáš Zato Jan 06 '16 at 16:30
  • This isn't unique to `qmake`, I had the same with `cmake`. Part fo the problem might be that both tools have a bit of an issue with header files, which might not always trigger a rebuild when needed. – MSalters Aug 23 '16 at 15:06
  • 3
    Thought "Rebuild" reran qmake automatically... apparently not. I did "Run qmake" at your suggestion, then "Rebuild" and it fixed my problem. – yano Jun 12 '17 at 23:48
  • Yup! "CLEAN" then "BUILD ALL" worked! – Francois Bertrand Nov 01 '21 at 15:58
60

Undefined reference to vtable may occur due to the following situation also. Just try this:

Class A Contains:

virtual void functionA(parameters)=0; 
virtual void functionB(parameters);

Class B Contains:

  1. The definition for the above functionA.
  2. The definition for the above functionB.

Class C Contains: Now you're writing a Class C in which you are going to derive it from Class A.

Now if you try to compile you will get Undefined reference to vtable for Class C as error.

Reason:

functionA is defined as pure virtual and its definition is provided in Class B. functionB is defined as virtual (NOT PURE VIRTUAL) so it tries to find its definition in Class A itself but you provided its definition in Class B.

Solution:

  1. Make function B as pure virtual (if you have requirement like that) virtual void functionB(parameters) =0; (This works it is Tested)
  2. Provide Definition for functionB in Class A itself keeping it as virtual . (Hope it works as I didn't try this)
  • @ilya1725 Your [suggested edit](http://stackoverflow.com/review/suggested-edits/15838120) isn't just fixing formatting and the like, you are also changing the answer, for example saying that class C is derived from B instead of A, and you are changing the second solution. This substantially changes the answer. In these cases, please leave a comment to the author instead. Thank you! – Fabio says Reinstate Monica Apr 14 '17 at 11:03
  • @FabioTurati what class is classC inheriting from then? The sentence isn't clear. Also, what is the meaning of "Class C Contains: "? – ilya1725 Apr 15 '17 at 00:21
  • @ilya1725 This answer isn't very clear, and I'm not against editing it and improving it. What I'm saying is that your edit changes the meaning of the answer, and that's too drastic a change. Hopefully, the author will step in and clarify what he meant (though he's been inactive for a long time). – Fabio says Reinstate Monica Apr 15 '17 at 02:23
  • Thanks! In my case, I had just 2 classes in my hierarchy. Class A declared a pure virtual method. Class B's declaration stated that it would override this method, but I had not yet written the overriden method's definition yet. – Nick Desaulniers Dec 31 '18 at 16:48
  • 1
    I just added "= 0" in virtual method and now it works. Thanks! – 8Observer8 Aug 05 '20 at 07:51
55

I simply got this error because my .cpp file was not in the makefile.

In general, if you forget to compile or link to the specific object file containing the definition, you will run into this error.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Guybrush Threepwood
  • 3,333
  • 2
  • 19
  • 26
  • Indeed, seems the message changes slightly from the usual `undefined reference to {function/class/struct}` when there are `virtual` things involved. Threw me off. – Keith M Oct 25 '17 at 22:10
28

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.

Shital Shah
  • 63,284
  • 17
  • 238
  • 185
23

I just ran into another cause for this error that you can check for.

The base class defined a pure virtual function as:

virtual int foo(int x = 0);

And the subclass had

int foo(int x) override;

The problem was the typo that the "=0" was supposed to be outside of the parenthesis:

virtual int foo(int x) = 0;

So, in case you're scrolling this far down, you probably didn't find the answer - this is something else to check for.

Hugo Alonso
  • 6,684
  • 2
  • 34
  • 65
Philip Thomas
  • 231
  • 2
  • 2
  • 2
    LOL, C++ gives you too many ways to accidentally shoot yourself in the foot. This looks like an error I am very likely to make. – Mark Lakata May 19 '21 at 21:31
12

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.

skuntsel
  • 11,624
  • 11
  • 44
  • 67
Iulian Popa
  • 121
  • 1
  • 2
9
  • Are you sure that CDasherComponent has a body for the destructor? It's definitely not here - the question is if it is in the .cc file.
  • From a style perspective, CDasherModule should explicitly define its destructor virtual.
  • It looks like CGameModule has an extra } at the end (after the }; // for the class).
  • Is CGameModule being linked against the libraries that define CDasherModule and CDasherComponent?
Stephen
  • 47,994
  • 7
  • 61
  • 70
  • - Yes, CDasherComponent has a destructor body in the cpp. I thought it was declared in the .h when I posted this. - Duly noted. - That was an extra bracket I added by mistake when stripping the documentation. - As far as I understand, yes. I've been modifying an automake file I did not write, but I've been following the patterns that have worked for other classes with the same inheritance pattern from the same classes, so unless I've made a stupid mistake (Entirely possible), I don't think that's it. – RyanG Jun 17 '10 at 20:29
  • @RyanG : try moving all virtual function definitions into the class definition. Make sure they're all there and see if the result changes. – Stephen Jun 17 '10 at 21:00
8

Not to cross post but. If you are dealing with inheritance the second google hit was what I had missed, ie. all virtual methods should be defined.

Such as:

virtual void fooBar() = 0;

See answare C++ Undefined Reference to vtable and inheritance for details. Just realized it's already mentioned above, but heck it might help someone.

Victor Häggqvist
  • 4,484
  • 3
  • 27
  • 35
7

For Qt User using CMakeList.txt

Add this line in your CMakeLists.txt : set(CMAKE_AUTOMOC ON)

As explain by Chris Morler if you forget to moc a header you get this error

Sebastien247
  • 423
  • 5
  • 16
6

This is a mis-feature in GCC. That is, the G++ compiler itself cannot complain about undefined virtual methods, since they can be defined elsewhere. But - it doesn't store information about which virtual members are missing; it only stores an UND-efined vtable symbol, which the linker then complains about.

Instead, if it were to list the missing members, the linker could have told you what they are.

There is an open bug about this issue against GCC: bug 42540. Unfortunately, it's 13-years-old :-(

einpoklum
  • 118,144
  • 57
  • 340
  • 684
4

In my case I'm using Qt and had defined a QObject subclass in a foo.cpp (not .h) file. The fix was to add #include "foo.moc" at the end of foo.cpp.

Stefan Monov
  • 11,332
  • 10
  • 63
  • 120
3

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.

Daniel Georgiev
  • 1,292
  • 16
  • 14
  • Commenting out the Q_OBJECT line made my simple test app build with a plain `g++ *.cpp ...`. (Needed something quick and dirty but qmake was full of grief.) – Nathan Kidd Jan 19 '17 at 20:24
2

If all else fails, look for duplication. I was misdirected by the explicit initial reference to constructors and destructors until I read a reference in another post. It's any unresolved method. In my case, I thought I had replaced the declaration that used char *xml as the parameter with one using the unnecessarily troublesome const char *xml, but instead, I had created a new one and left the other one in place.

Community
  • 1
  • 1
Jerry Miller
  • 921
  • 1
  • 8
  • 11
2

I think it's also worth mentioning that you will also get the message when you try to link to object of any class that has at least one virtual method and linker cannot find the file. For example:

Foo.hpp:

class Foo
{
public:
    virtual void StartFooing();
};

Foo.cpp:

#include "Foo.hpp"

void Foo::StartFooing(){ //fooing }

Compiled with:

g++ Foo.cpp -c

And main.cpp:

#include "Foo.hpp"

int main()
{
    Foo foo;
}

Compiled and linked with:

g++ main.cpp -o main

Gives our favourite error:

/tmp/cclKnW0g.o: In function main': main.cpp:(.text+0x1a): undefined reference tovtable for Foo' collect2: error: ld returned 1 exit status

This occure from my undestanding becasue:

  1. Vtable is created per class at compile time

  2. Linker does not have access to vtable that is in Foo.o

Adam Stepniak
  • 815
  • 6
  • 21
1

I tried all the detailed steps by JaMIT and still got stumped by this error. After a good amount of head-banging, I figured it out. I was careless. You should be able to reproduce this painful-to-look-at error w/ the following sample code.

[jaswantp@jaswant-arch build]$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --with-isl --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-install-libiberty --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-libunwind-exceptions --disable-werror gdc_include_dir=/usr/include/dlang/gdc
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.2.0 (GCC) 

// CelesetialBody.h
class CelestialBody{
public:
    virtual void Print();
protected:
    CelestialBody();
    virtual ~CelestialBody();
};
// CelestialBody.cpp
#include "CelestialBody.h"

CelestialBody::CelestialBody() {}

CelestialBody::~CelestialBody() = default;

void CelestialBody::Print() {}
// Planet.h
#include "CelestialBody.h"

class Planet : public CelestialBody
{
public:
    void Print() override;
protected:
    Planet();
    ~Planet() override;
};
// Planet.cpp
#include "Planet.h"

Planet::Planet() {}
Planet::~Planet() {}

void Print() {} // Deliberately forgot to prefix `Planet::`
# CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project (space_engine)
add_library (CelestialBody SHARED CelestialBody.cpp)
add_library (Planet SHARED Planet.cpp)
target_include_directories (CelestialBody PRIVATE ${CMAKE_CURRENT_LIST_DIR})  
target_include_directories (Planet PRIVATE ${CMAKE_CURRENT_LIST_DIR})    
target_link_libraries (Planet PUBLIC CelestialBody)

# hardened linker flags to catch undefined symbols
target_link_options(Planet 
    PRIVATE 
    -Wl,--as-needed
    -Wl,--no-undefined
)

And we get our favourite error.

$ mkdir build
$ cd build
$ cmake ..
$ make
[ 50%] Built target CelestialBody
Scanning dependencies of target Planet
[ 75%] Building CXX object CMakeFiles/Planet.dir/Planet.cpp.o
[100%] Linking CXX shared library libPlanet.so
/usr/bin/ld: CMakeFiles/Planet.dir/Planet.cpp.o: in function `Planet::Planet()':
Planet.cpp:(.text+0x1b): undefined reference to `vtable for Planet'
/usr/bin/ld: CMakeFiles/Planet.dir/Planet.cpp.o: in function `Planet::~Planet()':
Planet.cpp:(.text+0x3d): undefined reference to `vtable for Planet'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/Planet.dir/build.make:104: libPlanet.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:97: CMakeFiles/Planet.dir/all] Error 2
make: *** [Makefile:103: all] Error 2

What I've done in Planet.cpp should of course be resolved with this tip

  1. Look at your class definition. Find the first non-inline virtual function that is not pure virtual (not "= 0") and whose definition you provide (not "= default").

from JaMIT's answer. If there is anyone else who tried all the above and nothing worked, maybe you too, like me, carelessly forgot to prefix <ClassName>:: to one or more member functions.

Either I need to get my eyes checked or I need to get some sleep.

jaswantp
  • 33
  • 1
  • 5
0

I had this problem too when tried to implement Abstract Factory Pattern, but forgot to link some library. So, in case nothing was helped jet, check if all required libraries are linked

ivan.ukr
  • 2,853
  • 1
  • 23
  • 41
LaVuna47
  • 29
  • 6
0

FWIW I was able to avoid errors like these:

 ld: /usr/local/lib/libvmaf.a(svm.cpp.o):(.data.rel.ro._ZTI7QMatrix[_ZTI7QMatrix]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'

When linking a "C" project with a static library from a "C++" project, by adding -lstdc++ to the linking parameters. So it's gcc -lstdc++ now it works.

Most common way is to add the -lstdc++ to the libraries pkgconfig .pc file Library list. Or link with g++ instead.

rogerdpack
  • 62,887
  • 36
  • 269
  • 388