Undefined reference to 'vtable for xxx'
One or more of your .cpp files is not being linked in, or some non-inline functions in some class are not defined. In particular, takeaway::textualGame()
's implementation can't be found. Note that you've defined a textualGame()
at toplevel, but this is distinct from a takeaway::textualGame()
implementation - probably you just forgot the takeaway::
there.
What the error means is that the linker can't find the "vtable" for a class - every class with virtual functions has a "vtable" data structure associated with it. In GCC, this vtable is generated in the same .cpp file as the first listed non-inline member of the class; if there's no non-inline members, it will be generated wherever you instantiate the class, I believe. So you're probably failing to link the .cpp file with that first-listed non-inline member, or never defining that member in the first place.
You may take a look at this answer to an identical question (as I understand): https://stackoverflow.com/a/1478553 The link posted there explains the problem.
For quick solving your problem you should try to code something like this:
ImplementingClass::virtualFunctionToImplement(){...}
It helped me a lot.
If a class defines virtual methods outside that class, then g++ generates the vtable only in the object file that contains the outside-of-class definition of the virtual method that was declared first:
//test.h
struct str
{
virtual void f();
virtual void g();
};
//test1.cpp
#include "test.h"
void str::f(){}
//test2.cpp
#include "test.h"
void str::g(){}
The vtable will be in test1.o, but not in test2.o
This is an optimisation g++ implements to avoid having to compile in-class-defined virtual methods that would get pulled in by the vtable.
The link error you describe suggests that the definition of a virtual method (str::f in the example above) is missing in your project.
The first set of errors, for the missing vtable, are caused because you do not implement takeaway::textualGame()
; instead you implement a non-member function, textualGame()
. I think that adding the missing takeaway::
will fix that.
The cause of the last error is that you're calling a virtual function, initialData()
, from the constructor of gameCore
. At this stage, virtual functions are dispatched according to the type currently being constructed (gameCore
), not the most derived class (takeaway
). This particular function is pure virtual, and so calling it here gives undefined behaviour.
Two possible solutions:
- Move the initialisation code for
gameCore
out of the constructor and into a separate initialisation function, which must be called after the object is fully constructed; or - Separate
gameCore
into two classes: an abstract interface to be implemented bytakeaway
, and a concrete class containing the state. Constructtakeaway
first, and then pass it (via a reference to the interface class) to the constructor of the concrete class.
I would recommend the second, as it is a move towards smaller classes and looser coupling, and it will be harder to use the classes incorrectly. The first is more error-prone, as there is no way be sure that the initialisation function is called correctly.
One final point: the destructor of a base class should usually either be virtual (to allow polymorphic deletion) or protected (to prevent invalid polymorphic deletion).