使用抽象基类指向SDL_Rect类成员的指针的问题
Issue with a pointer to a SDL_Rect class member using an abstract base class
我有一个抽象基类,它有几个继承者,并且我创建了一个抽象基类的指针数组,这些指针将指向继承者:
抽象基类:
class Tile
{
public:
bool isPassable;
void setTileSet( SDL_Texture *Texture );
SDL_Rect* clip;
};
继承人:
class Floor: public Tile
{
public:
bool isPassable = true;
SDL_Rect clip = { 20, 0, 20, 20 };
};
指针数组:
Tile * dungeon[ z ][ x ][ y ] = {{{ nullptr }}};
当我试图通过指针数组访问成员SDL_Rect clip来blit tile时,什么也没有发生。程序编译并运行,但屏幕仍然默认为黑色:
dungeon[ 0 ][ 0 ][ 0 ] = &floor;
Draw::renderTexture( TILESET, REN, 0, 0, dungeon[ 0 ][ 0 ][ 0 ]->clip );
然而,当我只是使用类Floor来访问clip时,图像会很好地blit:
Draw::renderTexture( TILESET, REN, 0, 0, floor.clip );
我认为指针抽象基类可能没有加载,但当我试图编写代码以清除它时:
SDL_Rect error = { 0, 0, 20, 20 };
if( dungeon[ 0 ][ 0 ][ 0 ] != nullptr )
{
Draw::renderTexture( TILESET, REN, 0, 0, dungeon[ 0 ][ 0 ][ 0 ]->clip );
}
else
{
Draw::renderTexture( TILESET, REN, 0, 0, &error );
}
屏幕保持黑色
这是Draw::renderTexture函数,虽然我怀疑这是问题:
void Draw::renderTexture(SDL_Texture *texture, SDL_Renderer *render, int x, int y, SDL_Rect *clipping )
{
SDL_Rect destination;
destination.x = x;
destination.y = y;
destination.w = clipping->w;
destination.h = clipping->h;
SDL_RenderCopy( render, texture, clipping, &destination );
每层都有两个版本的isPassable: Floor::isPassable
和Tile::isPassable
。一个被初始化,另一个没有。你也有两个版本的剪辑。Floor::clip
未初始化,Tile::clip
未初始化。所以当你将地下城元素称为Tile时,它自然会访问未初始化的元素,然后灾难就来了。
你的代码说if( dungeon[ 0 ][ 0 ][ 0 ] != nullptr )...
没有帮助,因为Tile::clip
不是null;未初始化。
解决方案是消除isPassable和clip从Tile或Floor,所以你将只有一个副本,并不能访问错误的一个。
如果你想让它保持平铺,这些事情需要修复:
- 初始化它们,可能默认为false和NULL,在Tile的actor中——所有类的所有成员都需要初始化。这就是为什么你的if语句没有帮助
- 让Floor的actor调用Tile的actor,传递适当的值,如果Floors需要不同的初始值:
Floor () : Tile (true, 20, 0, 20, 20) {}
,也许。
您需要首先强制转换您的数组成员,以便它知道它正在查看哪个成员。目前你有一个Tile
实例的数组,所以当你把dungeon[ 0 ][ 0 ][ 0 ]->clip
传递给渲染函数时,系统会认为你指的是基类。
如果你把它改为(Floor*)(dungeon[ 0 ][ 0 ][ 0 ])->clip
,它应该工作。
然而,我要指出,这看起来像一个非常糟糕的设计,可能是因为您还没有完全理解继承和多态性,尽管您可能有一些理由这样做。
我个人会这样修改类,首先是基类:
class Tile
{
public:
Tile() :
m_passable(true) {}
Tile(bool passable, SDL_Rect& clip) :
m_passable(passable),
m_clip(clip) {}
virtual ~Tile() {}
inline void SetTileSet(SDL_Texture *texture) { m_texture = texture; }
inline SDL_Texture* GetTileSet() { return m_texture; }
inline void SetClip(SDL_Rect& clip) { m_clip = clip; }
inline SDL_Rect& GetClip() { return m_clip; }
inline void SetPassable(bool passable) { m_passable = passable; }
inline bool IsPassable() { return m_passable; }
protected:
bool m_passable;
SDL_Rect m_clip;
SDL_Texture* m_texture;
private:
Tile(Tile const&) = delete;
Tile& operator=(Tile const&) = delete;
};
,然后是继承类:
class Floor : public Tile
{
public:
Floor(bool passable, SDL_Rect& clip) :
Tile(passable, clip);
protected:
private:
Floor(Floor const&) = delete;
Floor& operator=(Floor const&) = delete;
};
当你想要一个新的Floor
实例时,只需执行:
SDL_Rect clip = { 0, 0, 20, 20 };
Floor* myFloor = new Floor(true, clip);
然后将其放入数组中,只需执行以下命令:
dungeon[ 0 ][ 0 ][ 0 ] = (Tile*)myFloor;
最后,如果你做了这些更改,你应该通过引用传递给你的渲染函数:
void Draw::renderTexture(SDL_Texture* texture, SDL_Renderer* render, int x, int y, SDL_Rect& clipping )
{
SDL_Rect destination = { x, y, clipping.w, clipping.h };
SDL_RenderCopy( render, texture, &clipping, &destination );
}
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 助记符和指向成员语法的指针
- 用于访问容器<T>数据成员的正确 API
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 嵌套在类中时无法设置成员数据
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 将函数类成员映射到类本身内部
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 将公共但非静态的成员函数与ALGLIB集成
- 多成员Constexpr结构初始化
- 我们可以访问一个不存在的联盟的成员吗