我多年来一直在开发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";
}*/
答案 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然后执行该函数。这允许您“覆盖”基本方法或使用基本方法,如果没有添加任何新的。虚析构函数在该表中为析构函数创建条目。如果没有虚拟析构函数的条目,则子类将没有条目,并且无法正确销毁基类,从而导致未定义的行为