0

回答済み: @AndyProwl が指摘してくれたおかげで、ScreenImage.Update() 関数に問題があることがわかりました。私はその関数の実装を書くことを行ったり来たりしていました (ScreenImage は更新する必要がないため、描画するだけでよいため)、実装を消去したときに、どういうわけか誤ってインターフェイスに Update 関数を残してしまいました...

お子様への警告とさせてください。~知れば知るほど~

元の質問:

私はゲームを作成しておりScreen、特定の画面上のアイテム (画像、テキスト、メニュー オプションなど) を追跡するオブジェクトを持っています。私の目標は、これらのアイテムをScreen抽象ScreenElementsオブジェクトの形で に渡し、次に、またはなどのより具体的なオブジェクトとして定義できるようにすることScreenImageですScreenText

ベクトル (基本的には ScreenElements のスタックとして扱う) を取得して、ベース オブジェクトへのポインターのベクトルにすることで、さまざまな継承されたクラスをうまく処理しようとして頭痛の種になりましたが、それはつまり、継承するオブジェクトを宣言する必要があることを意味します。ScreenElements宣言がスコープ外になったときにポインターが無効にならないように、関数の外から。そこで、「AddElement」を実行できるように Screen オブジェクトに関数を作成し、同じポインター メソッドが機能すると考えましたが、どうやら機能していないようです。

これが私のソースコードです。これが Screen.h です。

#ifndef SCREEN_H
#define SCREEN_H

#include <vector>

#include "ScreenElement.h"

class Screen
{
protected:
    bool enabled;

    std::vector<ScreenElement*> screen_elements;
public:
    //Gameloop Functions
    void Init();
    void Update(int ticks); //Enabled will likely determine if this is called
    void Draw(); //And this perhaps on a visible bool
    void Destroy();

    //Concept functions
    //void TransitionIn(data);
    //void TransitionOut(data);

    void AddElement(ScreenElement *Element); //function in question

    //Allow external use of enabled feature
    void ToggleEnable(bool Enabled) { enabled = Enabled; }
    bool IsEnabled() { return enabled; }
};

#endif // SCREEN_H

そして私のScreen.cppファイル

#include "Screen.h"

void Screen::Init()
{
    enabled = true;
}

void Screen::Update(int ticks)
{
    for(int i = 0; i < screen_elements.size(); i++)
        screen_elements[i]->Update(ticks);
}

void Screen::Draw()
{
    for(int i = 0; i < screen_elements.size(); i++)
        screen_elements[i]->Draw();
}

void Screen::Destroy()
{
    screen_elements.clear();
}

void Screen::AddElement(ScreenElement *Element)
{
    screen_elements.push_back(Element);
}

たとえば、ScreenImage など、継承された任意の形式の ScreenElement で動作し、それをベクターに格納するには、AddElement が必要です。

編集: ScreenElement クラスのソース コードもいくつか公開する必要があると思います。仮想デストラクタを追加しようとすると、継承されたクラスのコンストラクタに関連していると思われる最初のエラーに加えて、別のエラーが発生するだけでした (関数 ScreenImage::ScreenImage() で「vtable for ScreenImage」への未定義参照)。だからここに私のScreenElement.hがあります

#ifndef SCREENELEMENT_H
#define SCREENELEMENT_H

#include "Globals.h"

class ScreenElement
{
protected:
    s_Position screen_position;

    bool enabled;
public:
    virtual void Update(int ticks) {}
    virtual void Draw() {}
    virtual void Destroy() {}

    void ToggleEnable(bool Enabled) { enabled = Enabled; }
    bool IsEnabled() { return enabled; }
};

#endif // SCREENELEMENT_H 

これは、ScreenImage.h の作成に使用されました。

#ifndef SCREENIMAGE_H
#define SCREENIMAGE_H

#include "Globals.h"
#include "ScreenElement.h"
#include "SpriteSheet.h"

class ScreenImage: public ScreenElement
{
private:
    SpriteSheet *sprite_sheet;

    int sprite_sheet_frame;
public:
    void Init(SpriteSheet *Sprite_Sheet, float X, float Y, int SpriteSheetFrame = 0);
    void Update(int ticks);
    void Draw();
    void Destroy();
};

#endif // SCREENIMAGE_H

また、ScreenImage.cpp に基本関数の独自の実装があります。

4

1 に答える 1

0

SplashScreen という Screen のインスタンスと SplashScreen_Image という ScreenImage のインスタンスを初期化した後、「SplashScreen.AddElement(&ScreenImage);」を使用します。次に、「「vtable for ScreenImage」への未定義の参照がある」というエラーがスローされます

報告しているエラーから判断すると、問題は、クラスの仮想関数に対して宣言を提供したが、定義を提供していないことです。

たとえば、次のコードをコンパイルしようとすると、非常によく似たエラーが発生します。

struct X
{
    virtual void foo() { }
};

struct Y : X
{
    virtual void foo(); // Missing definition...
};

int main()
{
    Y y;
    y.foo(); // The compiler will complain about undefined reference
             // to vtable for Y...
}

対応するライブの例を次に示します。

于 2013-03-28T00:09:11.350 に答える