用嵌套类对VTable的未定义引用

Undefined reference to vtable with nested class

本文关键字:未定义 引用 VTable 嵌套      更新时间:2023-10-16

当我尝试编译以下代码时:

Alien::Action::Action(ActionType type, float x, float y) {
    Action::type = type;
    pos = Vec2(x, y);
}
Alien::Alien(float x, float y, int nMinions) {
    srand(time(NULL));
    sp = Sprite("img/alien.png");
    box = Rect(x, y, sp.GetWidth(), sp.GetHeight());
    box.x = x - box.h/2;
    box.y = y - box.w/2;
    hitpoints = 100;
    speed.x = 0.5;
    speed.y = 0.5;
    minionArray = std::vector<Minion>();
    for(int i = 0; i < nMinions; i++) {
        int a = rand()%501;
        float b = a/1000.0;
        float c = b+1;
        minionArray.emplace_back(Minion(get(), i*(360/nMinions), c));
    }
    taskQueue = std::queue<Action>();
}

IDE(Eclipse(给出以下错误消息:"对Alien的vtable''的不确定引用"(代码的第6行(。由于外星人内部没有虚拟方法,因此我不知道错误的原因。以下是外星人的标头文件:

#ifndef ALIEN_H_
#define ALIEN_H_
#include "GameObject.h"
class Alien: public GameObject {
private:
    class Action {
    public:
        enum ActionType {MOVE, SHOOT};
        ActionType type;
        Action(ActionType type, float x, float y);
        Vec2 pos;
    };
    int hitpoints;
    std::queue<Action> taskQueue;
    std::vector<Minion> minionArray;
public:
    Alien(float x, float y, int nMinions);
    ~Alien();
    void Update(float dt);
    void Render();
    Alien* get();
    bool IsDead();
};
#endif

GameObject的代码为:

#include "GameObject.h"
#include "InputManager.h"
#include "Camera.h"
#include "State.h"
    GameObject::~GameObject() {
    }
    GameObject* GameObject::get() {
        return this;
    }
    Minion::~Minion() {
    }
    Minion::Minion(GameObject* minionCenter, float arcOffset, float minionSize) {
        sp = Sprite("img/minion.png");
        center = minionCenter;
        translation = arcOffset;
        box = Rect(center->box.GetCenter().x+(cos(translation*M_PI/180)*200)-(sp.GetWidth()/2),
                   center->box.GetCenter().y+(sin(translation*M_PI/180)*200)-(sp.GetHeight()/2),
                   sp.GetWidth(), sp.GetHeight());
    }
    void Minion::Shoot(Vec2 pos) {
        State::AddObject(new BulletWheel(box.GetCenter().x, box.GetCenter().y, center->box.GetCenter().GetDX(pos.x),
                                         center->box.GetCenter().GetDY(pos.y), center->box.GetCenter().GetDS(pos), 0.3,
                                         translation, center->box.GetCenter(), "img/minionbullet1.png"));
    }
    void Minion::Update(float dt) {
        if(translation < 360)
            translation += 0.03*dt;
        else
            translation += 0.03*dt-360;
        /*rotation = translation-90;*/
        if(rotation < 360)
            rotation += 0.15*dt;
        else
            rotation += 0.15*dt-360;
        box.x = center->box.GetCenter().x+(200*cos((translation)*M_PI/180))-(box.w/2);
        box.y = center->box.GetCenter().y+(200*sin((translation)*M_PI/180))-(box.h/2);
    }
    void Minion::Render() {
        sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
    }
    bool Minion::IsDead() {
        return false;
    }
    Bullet::Bullet(float x, float y, float dx, float dy, float maxDistance, float speed, std::string sprite) {
        sp = Sprite(sprite);
        box = Rect(x-(sp.GetWidth()/2), y-(sp.GetHeight()/2), sp.GetWidth(), sp.GetHeight());
        Bullet::speed = Vec2(speed*(dx/maxDistance), speed*(dy/maxDistance));
        distanceLeft = maxDistance;
        rotation = atan2(dy, dx)*(180/M_PI);
    }
    void Bullet::Update(float dt) {
        if(distanceLeft > 0) {
            box.x += speed.x*dt;
            box.y += speed.y*dt;
            distanceLeft -= pow(pow(speed.x*dt,2)+pow(speed.y*dt,2),0.5);
        }
    }
    void Bullet::Render() {
        sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
    }
    bool Bullet::IsDead() {
        return (distanceLeft < 1) ? true : false;
    }
    Bullet* Bullet::get() {
        return this;
    }
    BulletWheel::BulletWheel(float x, float y, float dx, float dy, float maxDistance, float speed, float arcOffset, Vec2 center, std::string sprite) {
        sp = Sprite(sprite);
        sp.SetScaleX(2);
        sp.SetScaleY(2);
        box = Rect(x-(sp.GetWidth()/2), y-(sp.GetHeight()/2), sp.GetWidth(), sp.GetHeight());
        BulletWheel::speed = Vec2(speed*(dx/maxDistance), speed*(dy/maxDistance));
        distanceLeft = maxDistance;
        rotation = atan2(dy, dx)*(180/M_PI);
        translation = arcOffset;
        BulletWheel::center = center;
    }
    void BulletWheel::Update(float dt) {
        if(translation < 360)
            translation += 0.1*dt;
        else
            translation += 0.1*dt-360;
        if(distanceLeft > 0.01) {
            center.x += speed.x*dt;
            center.y += speed.y*dt;
            box.x = center.x+(200*cos((translation)*M_PI/180))-(box.w/2);
            box.y = center.y+(200*sin((translation)*M_PI/180))-(box.h/2);
            distanceLeft -= pow(pow(speed.x*dt,2)+pow(speed.y*dt,2),0.5);
        }
    }
    void BulletWheel::Render() {
        sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
    }
    bool BulletWheel::IsDead() {
        return distanceLeft < 1;
    }
    BulletWheel* BulletWheel::get() {
        return this;
    }

及其标头文件是: #ifndef GameObject_h_ #Define GameObject_h _

#include "Sprite.h"
#include "Rect.h"
#include "Vec2.h"
#include <queue>
#include <vector>
#include <cmath>
#include <ctime>
class GameObject{
private:
public:
    virtual ~GameObject();
    virtual void Update(float dt) = 0;
    virtual void Render() = 0;
    virtual bool IsDead() = 0;
    virtual GameObject* get();
    int rotation = 0;
    int translation = 0;
    Sprite sp = Sprite();
    Vec2 speed = Vec2();
    Rect box = Rect();
};
class Minion : public GameObject {
private:
    GameObject* center;
public:
    Minion(GameObject* minionCenter, float arcOffset, float minionSize = 1);
    ~Minion();
    void Shoot(Vec2 pos);
    void Update(float dt);
    void Render();
    bool IsDead();
    Minion* get();
};
class Bullet : public GameObject {
private:
    float distanceLeft;
public:
    Bullet(float x, float y, float dx, float dy, float maxDistance, float speed, std::string sprite);
    void Update(float dt);
    void Render();
    bool IsDead();
    Bullet* get();
};
class BulletWheel : public GameObject {
private:
    float distanceLeft;
    Vec2 center;
public:
    BulletWheel(float x, float y, float dx, float dy, float maxDistance, float speed, float arcOffset, Vec2 center, std::string sprite);
    void Update(float dt);
    void Render();
    bool IsDead();
    BulletWheel* get();
};
#endif /* GAMEOBJECT_H_ */

gameObject有虚拟函数,在alien.cpp中声明:

void Alien::Update(float dt) {
    if(rotation > 0)
        rotation -= 0.1*dt;
    else
        rotation -= 0.1*dt+360;
    if(InputManager::GetInstance().MousePress(RIGHT_MOUSE_BUTTON)) {
        taskQueue.push(Action(Action::MOVE,(InputManager::GetInstance().GetMouseX() + Camera::GetInstance().pos.x - (box.w/2)),
                                           (InputManager::GetInstance().GetMouseY() + Camera::GetInstance().pos.y - (box.h/2))));
    }
    if(InputManager::GetInstance().MousePress(LEFT_MOUSE_BUTTON)) {
        taskQueue.push(Action(Action::SHOOT,(InputManager::GetInstance().GetMouseX() + Camera::GetInstance().pos.x),
                                            (InputManager::GetInstance().GetMouseY() + Camera::GetInstance().pos.y)));
    }
    if(taskQueue.size() > 0) {
        Vec2 pos = taskQueue.front().pos;
        if(taskQueue.front().type == Action::MOVE) {
            float cos = (box.GetDX(pos.x)/box.GetDS(pos));
            float sin = (box.GetDY(pos.y)/box.GetDS(pos));
            if(cos != cos) {
                cos = 0;
            }
            if(sin != sin) {
                sin = 0;
            }
            if((box.x+speed.x*cos*dt > pos.x && pos.x > box.x) || (box.x+speed.x*cos*dt < pos.x && pos.x < box.x)) {
                box.x = pos.x;
            }
            else {
                box.x += speed.x*cos*dt;
            }
            if((box.y+speed.y*sin*dt > pos.y && pos.y > box.y) || (box.y+speed.y*sin*dt < pos.y && pos.y < box.y)) {
                box.y = pos.y;
            }
            else {
                box.y += speed.y*sin*dt;
            }
            if(box.x == pos.x && box.y == pos.y) {
                taskQueue.pop();
            }
        }
        else {
            for(unsigned i = 0; i < minionArray.size(); i++) {
            minionArray.at(i).Shoot(pos);
            taskQueue.pop();
            }
        }
    }
    for(unsigned i = 0; i < minionArray.size(); i++) {
        minionArray.at(i).Update(dt);
    }
}
void Alien::Render() {
    sp.Render(box.x - Camera::GetInstance().pos.x, box.y - Camera::GetInstance().pos.y, rotation);
    if(minionArray.size() > 0) {
        for(unsigned i = 0; i < Alien::minionArray.size(); i++) {
            minionArray.at(i).Render();
        }
    }
}
bool Alien::IsDead() {
    return (Alien::hitpoints <= 0);
}

编辑:外星人的破坏者缺少。

GameObject派生的所有类都必须定义GameObject中的所有纯虚拟函数。就您而言,这是:

virtual void Update(float dt) = 0;
virtual void Render() = 0;
virtual bool IsDead() = 0;

这是一个类似的问题,还有更多信息。希望这会有所帮助!