-1

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
Xelphin
  • 311
  • 3
  • 10
  • 1
    You likely are not building and linking the `Barfight.cpp` file. – ChrisMM Jun 06 '22 at 17:02
  • Please show the exact compilation commands you're using. – cigien Jun 06 '22 at 17:03
  • ```g++ -std=c++11 -Wall -Werror -pedantic-errors -DNDEBUG -g *.cpp -o my_test``` from the root folder not sufficient? (That's what I use) – Xelphin Jun 06 '22 at 17:03
  • Please include that information as an edit to the question, instead of a comment. – cigien Jun 06 '22 at 17:04
  • Are all the cpp files in the root dir? It will not go into your folders recursively adding all cpp files in the whole tree. – drescherjm Jun 06 '22 at 17:05
  • 2
    @Xelphin The shell replaces `*.cpp` with a list of all files _in the current directory_ which end in `.cpp`. If you have subdirectories with files you want to use that doesn't work. I recommend to list all `.cpp` files explicitly or even better use a proper build system, e.g. CMake. – user17732522 Jun 06 '22 at 17:08
  • What command do you recommend? – Xelphin Jun 06 '22 at 17:10
  • From your latest update `test.cpp` will be the only file compiled. – drescherjm Jun 06 '22 at 17:10
  • @Xelphin -- Use a build system, make file, IDE that is friendly enough, or read the g++ manual as to how to compile and link multi-module C++ programs. Don't guess at it, as you can see, your guess did something you didn't expect it to do. – PaulMcKenzie Jun 06 '22 at 17:11
  • Are you compiling from the shell or using VSCode? If the latter my answer: [https://stackoverflow.com/questions/70856563/vscode-g-it-isnt-finding-cpp-definition-files/70856902#70856902](https://stackoverflow.com/questions/70856563/vscode-g-it-isnt-finding-cpp-definition-files/70856902#70856902) should help as it is the exact same problem. – drescherjm Jun 06 '22 at 17:11
  • Upwards relative directory structure traversal `#include "../Players/Player.h"` does not scale well. The relative position is rigid, and makes restructuring the code a painful exercise. Better to use `#include "Players/Player.h"` and provide your compiler the include path root location (the `..` part, or absolute path). – Eljay Jun 06 '22 at 17:15
  • @Xelphin As mentioned above, have a look at tutorials for CMake, makefiles and so on or use an IDE that handles this for you automatically. A minimal fix to your problem would be to add `*/*.cpp` on the command line, which will add all `.cpp` files in a (1-level deeper) subdirectory. That is however not a solution long-term or for larger projects. – user17732522 Jun 06 '22 at 17:15
  • 1
    `void Barfight::applyEncounter(Player& player) const` ≠ `void Barfight::applyEncounter(Player& player)`, note the missing `const` which makes it a different signature. – Eljay Jun 06 '22 at 17:17
  • @Elijay updated my question from what you wrote – Xelphin Jun 06 '22 at 18:05

1 Answers1

2

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.

Marek R
  • 32,568
  • 6
  • 55
  • 140