简体   繁体   English

抽象类C ++

[英]abstract classes C++

So it is my understanding that to make a class abstract in c++ you have to create one, just one, pure virtual method in that class. 因此,据我了解,要使用c ++将类抽象化,您必须在该类中创建一个(仅一个)纯虚拟方法。 In my code i create an abstract GameObject class, which is inherited by my Player class, but the problem is i get errors in my Player.cpp saying error LNK2001: unresolved extrenal symbol "public:virtual void__thiscall GameObject::Load(void)" (?Load@GameObject@@UAEXXZ) for every method except the initialise, and this gets fixed when i set them all = 0, im just wondering why 在我的代码中,我创建了一个抽象的GameObject类,该类由Player类继承,但是问题是我在Player.cpp中遇到错误,提示错误LNK2001:未解决的外部符号“ public:virtual void__thiscall GameObject :: Load(void)” (?Load @ 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);
}

Every virtual method which might be called through a base class pointer that isn't pure virtual needs to have an implementation. 可能通过不是纯虚拟的基类指针调用的每个虚拟方法都需要实现。

You seem to have a backwards idea of how abstract/virtual works. 您似乎对抽象/虚拟的工作方式有一个倒退的想法。 You don't choose to make a class abstract, why would you? 您不选择将类抽象化,为什么呢? You choose to make a member function pure virtual, because there is no sensible implementation for it. 您选择使成员函数成为纯虚拟的,因为没有明智的实现。 Then, as a consequence of having a pure virtual function, the class becomes abstract. 然后,由于具有纯虚函数,该类将变为抽象。

The class becoming abstract does not mean that every one of its functions suddenly becomes pure virtual. 该类成为抽象类并不意味着其所有功能突然变成纯虚拟的。

Your error is a linker error. 您的错误是链接器错误。 The linker was looking for the implementation of the GameObject::Load function, which you didn't provide. 链接程序正在寻找GameObject::Load函数的实现,而您没有提供。 If you mark the function as pure virtual, the linker won't look for an implementation. 如果将功能标记为纯虚函数,则链接器将不会寻找实现。

Some compilers require that for each signature the virtual keyword would specified only once, in the base class. 一些编译器要求对于每个签名,虚拟关键字在基类中只能指定一次。 Try this: 尝试这个:

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();
...
};

if you don't need the public GameObject::Initialise method be pure virtual, at least give it an empty body, like this 如果您不需要公共GameObject :: Initialise方法是纯虚拟的,至少给它一个空的主体,像这样

class GameObject
{
public:
    void Initialise() {}
    ...
};

Another conjecture: do you have, by any chance, any instantiations of GameObject in your code? 另一个猜想:您的代码中是否有GameObject的任何实例化? Do you have something like this: 你有这样的东西吗?

GameObject go;

or something like this: 或类似这样的东西:

void foo( GameObject go );

or something like this: 或类似这样的东西:

GameObject bar();

or something like this: 或类似这样的东西:

vector<GameObject> all_my_objects;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM