【问题标题】:Using an inherited class in a function?在函数中使用继承的类?
【发布时间】:2013-03-27 23:44:25
【问题描述】:

回答:感谢@AndyProwl 向我指出了一些问题,我发现问题出在我的 ScreenImage.Update() 函数中。我在为该函数编写实现时来回失败(因为 ScreenImage 不需要更新,它只需要绘制)并且当我删除实现时不知何故不小心将更新函数留在了我的界面上......

这是对您的孩子的警告。 ~你知道的越多~

原问题:

我正在制作一个游戏,我有一个 Screen 对象来跟踪给定屏幕上的项目(即图像、文本、菜单选项等)。我的目标是以抽象ScreenElements 对象的形式将这些项目传递给Screen,该对象又可以定义为更具体的对象,例如ScreenImageScreenText 等。

我头疼地试图让向量(基本上将其视为 ScreenElements 的堆栈)通过使其成为指向基础对象的指针向量来与不同的继承类很好地配合,但这意味着我必须在函数外部声明从ScreenElements 继承的对象,因此当声明超出范围时指针不会变为无效。然后我在我的 Screen 对象中创建了一个函数来允许我“AddElement”,我认为相同的指针方法可以工作......它显然没有。

这是我的源代码,只是为了澄清问题。这是 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);
}

我需要我的 AddElement 来处理任何继承形式的 ScreenElement,例如 ScreenImage,并将其存储到向量中。

编辑:我想我也应该从我的 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 中有自己的基本函数实现。

【问题讨论】:

  • "我认为相同的指针方法可以工作......它显然没有。" - 那么问题是什么?
  • 你是从“ScreenElement”继承“ScreenImage”还是“ScreenText”?你如何创建屏幕元素?此处提供的信息没有说明任何内容。
  • @AndyProwl 当我通过函数传递“ScreenElement”的指针时,它不会接受指向继承的“ScreenImage”的指针,即使理论上它们应该是相同的。所以函数“AddElement()”只是说“没有可接受的从 *ScreenImage 到 *ScreenElement 的转换”或类似的东西。
  • 你能展示一些重现问题的代码吗?您发布的大部分内容似乎无关紧要。
  • @AniMerrill:问题可能出在您调用该函数的方式上,而不是函数本身

标签: c++ function inheritance polymorphism


【解决方案1】:

在初始化一个名为 SplashScreen 的 Screen 实例和一个名为 SplashScreen_Image 的 ScreenImage 之后,我使用“SplashScreen.AddElement(&ScreenImage);”然后它给我一个关于“未定义对“用于 ScreenImage 的 vtable”的引用的错误

从您报告的错误来看,问题似乎是您为类的某些虚函数提供了声明,而不是定义

例如,尝试编译以下代码会产生非常相似的错误:

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...
}

这里是对应的live example

【讨论】:

  • 我现在在编辑中添加了我的课程源代码。我从未声明构造函数或析构函数,因为到目前为止,我的游戏设计都不需要。
  • @AniMerrill:您是否提供了所有虚拟成员函数的定义?
  • 是的,尽管在基类中它们只是 {},因为我目前不希望它们做任何事情。但是在……废话。是的,显然我没有改变更新。我现在觉得有点傻。
  • @AniMerrill: :D 别担心,我们都去过那里
  • 我刚刚在将其放入实现而不是放入实现之间失败了,但显然将其留在了界面中。好尴尬哈哈哈
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-29
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
相关资源
最近更新 更多