0

I've been developing C# and Java (among many other languages) for many years, and I'm just now getting my feet wet in C++. I've buried myself in resources on inheritance and classes, but I just can't seem to figure out how to get rid of this pesky error.

My code:

Entity.h:

#ifndef ENTITY_H
#define ENTITY_H

#include <iostream>

class Entity
{
public:
    std::string m_name;

    void update(float delta);
    Entity();

private:
    virtual void step(float delta);
};

#endif

Entity.cpp:

#include "Entity.h"

Entity::Entity()
{
    m_name = "Generic Entity";
}

void Entity::update(float delta)
{
    step(delta);
}

void Entity::step(float delta) {}

Player.h:

#ifndef PLAYER_H
#define PLAYER_H

#include "Entity.h"

class Player : public Entity
{
public:
    Player();

private:
    virtual void step(float delta);

    virtual void draw() const;
};

#endif

Player.cpp:

#include "Player.h"

Player::Player()
{
    m_name = "Player";
}

void Player::step(float delta) {}

void Player::draw() const {}

Main.cpp:

int main()
{
    return 0;
}

As you can see, I'm not doing anything with the classes, but I'm getting these errors:

Error    3    error LNK1120: 1 unresolved externals    C:\[...]\Debug\ConsoleApplication1.exe    ConsoleApplication11
Error    2    error LNK2019: unresolved external symbol "public: __thiscall Entity::Entity(void)" (??0Entity@@QAE@XZ) referenced in function "public: __thiscall Player::Player(void)" (??0Player@@QAE@XZ)    C:\[...]\ConsoleApplication1\Player.obj    ConsoleApplication1

UPDATE: The code magically works when I comment out the following code in Player.cpp:

/*Player::Player()
{
    m_name = "Player";
}*/
Entity
  • 7,972
  • 21
  • 79
  • 122
  • how do you compile it? and private virtual method doesn't really make sense – Bryan Chen Nov 02 '14 at 03:30
  • It looks like you're not linking the object code for `Entity.cpp`, most likely because you're not compiling that file. Also note that to use `std::string` you should include ``, not ``. While the code as-is may compile with some compilers, it may not compile with others. – Cheers and hth. - Alf Nov 02 '14 at 03:30
  • @BryanChen Microsoft Visual Studio Express 2013 for Windows Desktop – Entity Nov 02 '14 at 03:30

1 Answers1

1

It looks like Entity isn't linked to player. Make sure output shows it compiling and that they are both added to your project

You also need to define a virtual destructor in your base class

Edit:

It doesn't have to compile first, my mistake. In C/C++, program creation is in two steps. First the compiler creates obj files for your cpp files, such as Entity.obj, Player.obj and so on. Then the linker will bundle everything together.

In Player.cpp, you say that you will have a class named Entity at some point, so the compiler finds the definition of that class in the .h file. Player.cpp then gets transformed into executable code in Player.obj but it won't contain the Entity.obj executable code. The compilation step works.

Then the linker will try to parse Player.obj and find Entity.obj that the compiler said will exists. If it doesn't then you get the "undefined reference" error, because the definitions found do not match the actual executable.

The virtual destructor is mandatory. The way inheritance works in C++ is with the virtual table. For each class with inheritance, a virtual table (vtable) is created with the virtual entries. When the linking step is performed, the linker will fill the vtable with the actual function. When the code executes, it checks the vtable for that class then execute that function. This allows you to "override" base methods or use the base method if nothing new is added. The virtual destructor creates the entry in that table for the destructor. If there is no entry for a virtual destructor, then the child class will not have an entry and won't be able to destroy the base class properly, which results in undefined behavior

Eric
  • 19,525
  • 19
  • 84
  • 147
  • Here's the build order: `Player.cpp, main.cpp, Entity.h, Entity.cpp`. Why do I *need* a virtual destructor? – Entity Nov 02 '14 at 03:37
  • Entity.h SHOULD NOT be built. It does not contain executable code – Eric Nov 02 '14 at 03:48
  • 2
    I feel silly now, that was the whole problem. Entity.h was marked to be compiled by visual studio. Your explanation was also very helpful, thank you :) – Entity Nov 02 '14 at 03:52