所以我的理解是,要在c ++中创建一个类抽象,你必须在该类中创建一个纯粹的虚拟方法。在我的代码中,我创建了一个抽象的GameObject类,它由我的Player类继承,但问题是我在我的Player.cpp中得到错误说错误LNK2001:未解析的extrenal符号“public:virtual void__thiscall GameObject :: Load(void)” (?加载@ GameObject @@ UAEXXZ)除了初始化之外的每个方法,当我将它们设置为全部= 0时,这会得到修复,我只是想知道为什么
// Abstract class to provide derived classes with common attributes
#include <SDL.h>
#include "AnimationManager.h"
#include "Debug.h"
#include "InputHandler.h"
class GameObject
{
public:
virtual void Initialise() = 0;
virtual void Load();
virtual void HandleEvents();
virtual void Update();
virtual void Draw();
Vector2D* position;
int currantFrame;
SDL_Renderer* renderer;
float speed;
bool alive;
};
#include "GameObject.h"
class Player : public GameObject
{
public:
virtual void Initialise();
virtual void Load();
virtual void HandleEvents();
virtual void Update();
virtual void Draw();
Player(SDL_Renderer* r);
~Player();
};
#include "Player.h"
Player::Player(SDL_Renderer* r)
{
renderer = r;
}
Player::~Player()
{
}
void Player::Initialise()
{
position = new Vector2D(10, 10);
currantFrame = 0;
}
void Player::Load()
{
TheAnimationManager::Instance()->load("Assets/circle.png", "player", renderer);
}
void Player::HandleEvents()
{
SDL_Event event;
if (SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_a:
DEBUG_MSG("A Pressed");
position->m_x -= 10;
break;
case SDLK_d:
DEBUG_MSG("D Pressed");
position->m_x += 10;
break;
}
break;
}
}
}
void Player::Update()
{
Vector2D* p = TheInputHandler::Instance()->GetMousePosition();
DEBUG_MSG(p->GetY());
DEBUG_MSG(p->GetX());
currantFrame = int(((SDL_GetTicks() / 100) % 4));
}
void Player::Draw()
{
TheAnimationManager::Instance()->Animate("player", (int)position->GetX(), (int)position->GetY(), 90, 82, 0, currantFrame, renderer, SDL_FLIP_NONE);
}
答案 0 :(得分:5)
可能通过非纯虚拟基类指针调用的每个虚方法都需要有一个实现。
您似乎对抽象/虚拟的工作原理有一个倒退的想法。你不选择抽象课,为什么?您选择将成员函数设置为纯虚拟,因为它没有合理的实现。然后,由于具有纯虚函数,该类变为抽象。
变成抽象的类并不意味着它的每一个函数都突然变成纯虚的。
您的错误是链接器错误。链接器正在寻找您未提供的GameObject::Load
函数的实现。如果将该函数标记为纯虚函数,则链接器将不会查找实现。
答案 1 :(得分:0)
某些编译器要求对于每个签名,virtual关键字只在基类中指定一次。试试这个:
class GameObject
{
public:
virtual void Initialise() = 0;
virtual void Load() = 0;
virtual void HandleEvents() = 0;
virtual void Update() = 0;
virtual void Draw() = 0;
...
};
class Player : public GameObject
{
public:
void Initialise();
void Load();
void HandleEvents();
void Update();
void Draw();
...
};
答案 2 :(得分:0)
如果你不需要公共GameObject :: Initialise方法是纯虚拟的,至少给它一个空体,就像这样
class GameObject
{
public:
void Initialise() {}
...
};
答案 3 :(得分:0)
另一个猜想:您是否有任何机会在代码中实现GameObject的任何实例化?你有这样的东西:
GameObject go;
或类似的东西:
void foo( GameObject go );
或类似的东西:
GameObject bar();
或类似的东西:
vector<GameObject> all_my_objects;