重载默认构造函数导致错误

时间:2014-11-02 03:25:05

标签: c++ inheritance

我多年来一直在开发C#和Java(以及许多其他语言),而且我现在才开始习惯使用C ++。我已经把自己埋在了继承和课程的资源中,但我似乎无法弄清楚如何摆脱这个讨厌的错误。

我的代码:

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;
}

正如您所看到的,我没有对课程做任何事情,但我收到了这些错误:

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

更新:当我在Player.cpp中注释掉以下代码时,代码会神奇地起作用:

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

1 个答案:

答案 0 :(得分:1)

看起来Entity没有链接到玩家。确保输出显示它已编译并且它们都已添加到项目中

您还需要在基类中定义虚拟析构函数

编辑:

我没有先编译,我的错误。在C / C ++中,程序创建分为两个步骤。首先,编译器为您的cpp文件创建obj文件,例如Entity.obj,Player.obj等。然后链接器将所有内容捆绑在一起。

在Player.cpp中,您说在某些时候您将有一个名为Entity的类,因此编译器会在.h文件中找到该类的定义。然后Player.cpp转换为Player.obj中的可执行代码,但它不包含Entity.obj可执行代码。编译步骤有效。

然后链接器将尝试解析Player.obj并找到编译器声称将存在的Entity.obj。如果没有,则会出现“未定义的引用”错误,因为找到的定义与实际的可执行文件不匹配。

虚拟析构函数是必需的。继承在C ++中的工作方式是使用虚拟表。对于每个具有继承的类,将使用虚拟条目创建虚拟表(vtable)。执行链接步骤时,链接器将使用实际函数填充vtable。当代码执行时,它会检查该类的vtable然后执行该函数。这允许您“覆盖”基本方法或使用基本方法,如果没有添加任何新的。虚析构函数在该表中为析构函数创建条目。如果没有虚拟析构函数的条目,则子类将没有条目,并且无法正确销毁基类,从而导致未定义的行为