Search code examples
c++inheritanceinterfacevirtual-functions

Implementing virtual functions in child's .cpp causes "undefined reference to `vtable for <child's class>`"


I have an interface:

//Card.h
#include "../Players/Player.h"

class Card {
public:
    virtual void applyEncounter(Player& player) const = 0;
    virtual void printInfo() const = 0;
    virtual ~Card() {}
};

And a class that inherits from it

// Barfight.h
// ...
#include "../Players/Player.h"
#include "Card.h"

class Barfight : public Card {
public:

    Barfight() {}
    void applyEncounter(Player& player) const override;
    void printInfo() const override;
    virtual ~Barfight() {};

private:
    static const int LOSE_HP = 10;

};
// Barfight.cpp
#include "Card.h"
#include "Barfight.h"
#include "../Players/Player.h"

void Barfight::applyEncounter(Player& player) const override
{

}

void Barfight::printInfo() const override
{
  std::cout << "I don't get printed at all" << endl;
}

But when I run in a main() function:

Barfight myBarfightCard;
myBarfightCard.printInfo();

Command Line (from the root directory):

g++ -std=c++11 -Wall -Werror -pedantic-errors -DNDEBUG -g *.cpp -o my_test

This gives me the error:

<...>/test.cpp:145: undefined reference to `Barfight::printInfo() const'
/usr/bin/ld: /tmp/ccNVNgLR.o: in function `Barfight::Barfight()':
<...>/Cards/Barfight.h:14: undefined reference to `vtable for Barfight'
/usr/bin/ld: /tmp/ccNVNgLR.o: in function `Barfight::~Barfight()':
<...>/Cards/Barfight.h:35: undefined reference to `vtable for Barfight'
collect2: error: ld returned 1 exit status

However, if I do this:

// Barfight.h
// ...
    void applyEncounter(Player& player) const override {};

    void printInfo() const override {};
// ...

I don't get an error, but it doesn't print what is inside of the Barfight.cpp. How do I still do an implementation that works in the .cpp?

Files:

  • test.cpp (has main())
  • Players
    • Player.h
    • Player.cpp
  • Cards
    • Cards.h
    • Barfight.h
    • Barfight.cpp

Solution

  • You are building your project in wrong way.

    You've have shown this:

    g++ -std=c++11 -Wall -Werror -pedantic-errors -DNDEBUG -g *.cpp -o my_test
    

    What is scary you have a wild card here and your code uses relative paths. This is straight way to forgot some file, what will lead to linking issue. Note that wild card is not recursive it doesn't reach into sub directories.

    However, if I do this:

    // Barfight.h
    // ...
        void applyEncounter(Player& player) override {};
    
        void printInfo() override {};
    // ...
    

    I don't get an error, but it doesn't print what is inside of the Barfight.cpp.

    This means that when you did build it you didn't liked code properly and result of compilation of Barfight.cpp was not used.

    Learn some build manager ASAP. cmake is most common used tool. There are other tools like bazel, Make, Ninja or IDE specific project files.