C++ 如何摆脱这里的动态角色?

C++ 如何摆脱这里的动态角色?,c++,rtti,dynamic-cast,C++,Rtti,Dynamic Cast,我正在为我的游戏制作一个简单的图形引擎 这是接口部分: class Texture { ... }; class DrawContext { virtual void set_texture(Texture* texture) = 0; } 这是实施部分: class GLTexture : public Texture { public: ... GLuint handle; }; void GLDrawContext::set_texture(Textur

我正在为我的游戏制作一个简单的图形引擎

这是接口部分:

class Texture { ... };

class DrawContext 
{ 
    virtual void set_texture(Texture* texture) = 0; 
}
这是实施部分:

class GLTexture : public Texture
{
public:
    ...
    GLuint handle;
};

void GLDrawContext::set_texture(Texture* texture)
{
    // Check if it's GLTexture, otherwise do nothing.
    if (GLTexture* gl_texture = dynamic_cast<GLTexture*>(texture))
    {
        glBindTexture(GL_TEXTURE_2D, gl_texture->handle);
    }
}
class-GLTexture:公共纹理
{
公众:
...
胶柄;
};
void GLDrawContext::设置纹理(纹理*纹理)
{
//检查它是否为GLTexture,否则什么也不做。
if(GLTexture*gl_texture=dynamic_cast(纹理))
{
glBindTexture(GL_纹理\u 2D,GL_纹理->句柄);
}
}

在这里使用dynamic_cast有意义吗?有什么方法可以避免吗?

当然可以,使用static\u cast,但是如果传入一个伪指针,则会丢失一些错误处理。我们使用assert\u cast思想来动态调试构建,使用static for release来绕过RTTI来解决这类问题。

当然,可以使用static\u cast,但是如果传入一个伪指针,将丢失一些错误处理。我们使用assert_cast思想来动态调试构建和静态发布,以绕过RTTI进行此类操作。

我认为避免动态_cast的标准方法是向Texture类添加虚拟方法:

virtual int get_texture_handle() const {return -1;}
virtual int get_texture_handle() const {return gl_texture->handle;}
然后仅在GLTexture类中重写该方法:

virtual int get_texture_handle() const {return -1;}
virtual int get_texture_handle() const {return gl_texture->handle;}
那么您的呼叫代码如下所示:

int handle = texture->get_texture_handle();
if (handle >= 0) glBindTexture(GL_TEXTURE_2D, handle);

我认为避免动态_cast的标准方法是向纹理类添加虚拟方法:

virtual int get_texture_handle() const {return -1;}
virtual int get_texture_handle() const {return gl_texture->handle;}
然后仅在GLTexture类中重写该方法:

virtual int get_texture_handle() const {return -1;}
virtual int get_texture_handle() const {return gl_texture->handle;}
那么您的呼叫代码如下所示:

int handle = texture->get_texture_handle();
if (handle >= 0) glBindTexture(GL_TEXTURE_2D, handle);

你能试着扭转这种担忧吗

class Texture
{
public:
    virtual void set_texture() = 0;
};

class GLTexture : public Texture
{
public:
    virtual void set_texture();
    GLuint handle;
};

void GLTexture::set_texture()
{
    glBindTexture(GL_TEXTURE_2D, handle);
}


你能试着扭转这种担忧吗

class Texture
{
public:
    virtual void set_texture() = 0;
};

class GLTexture : public Texture
{
public:
    virtual void set_texture();
    GLuint handle;
};

void GLTexture::set_texture()
{
    glBindTexture(GL_TEXTURE_2D, handle);
}


一种稍微不同的方法,涉及修改纹理类

class Texture 
{
    virtual void bind_texture(){} 
};
class GLTexture : public Texture 
{
    virtual void bind_texture(); 
};
void GLTexture::bind_texture()
{
    glBindTexture(GL_TEXTURE_2D, handle);
}
class DrawContext 
{ 
    virtual void set_texture(Texture* texture) = 0; 
};
class GLDrawContext : public DrawContext
{
    virtual void set_texture(Texture* texture);
};
void GLDrawContext::set_texture(Texture* texture)
{
    if( texture )
        texture->bind_texture();
}

一种稍微不同的方法,涉及修改纹理类

class Texture 
{
    virtual void bind_texture(){} 
};
class GLTexture : public Texture 
{
    virtual void bind_texture(); 
};
void GLTexture::bind_texture()
{
    glBindTexture(GL_TEXTURE_2D, handle);
}
class DrawContext 
{ 
    virtual void set_texture(Texture* texture) = 0; 
};
class GLDrawContext : public DrawContext
{
    virtual void set_texture(Texture* texture);
};
void GLDrawContext::set_texture(Texture* texture)
{
    if( texture )
        texture->bind_texture();
}

作为替代方案,您可以尝试使用泛型来摆脱动态强制转换。泛型将允许您在编译时捕获错误(您永远无法将DirectX纹理传递给GL DrawContext)。此外,动态调度不会产生任何成本,编译器应该能够进行内联

namespace GL_impl {

struct Texture {
    GLuint handle;
};

struct DrawContext {
    void set_texture(Texture* texture)
    {
        glBindTexture(GL_TEXTURE_2D, texture->handle);
    }
};

} // GL_impl


struct use_GL {
    typedef GL_impl::Texture Texture;
    typedef GL_impl::DrawContext DrawContext;
};

template <class use_impl>
void f()
{
    typedef typename use_impl::Texture Texture;
    typedef typename use_impl::DrawContext DrawContext;

    Texture t;
    DrawContext ctx;
    ctx.set_texture(&t);
}

void call_f_with_gl()
{
    f<use_GL>();
}
名称空间GL\u impl{
结构纹理{
胶柄;
};
结构DrawContext{
空集_纹理(纹理*纹理)
{
glBindTexture(GL_TEXTURE_2D,纹理->句柄);
}
};
}//GL_impl
结构使用{
typedef GL_impl::纹理;
typedef GL_impl::DrawContext DrawContext;
};
样板
void f()
{
typedef typename使用_impl::纹理;
typedef typename use_impl::DrawContext DrawContext;
纹理t;
DrawContext-ctx;
ctx.set_纹理(&t);
}
无效调用\u f\u和\u gl()
{
f();
}

作为替代,您可以尝试使用泛型来摆脱动态强制转换。泛型将允许您在编译时捕获错误(您永远无法将DirectX纹理传递给GL DrawContext)。此外,动态调度不会产生任何成本,编译器应该能够进行内联

namespace GL_impl {

struct Texture {
    GLuint handle;
};

struct DrawContext {
    void set_texture(Texture* texture)
    {
        glBindTexture(GL_TEXTURE_2D, texture->handle);
    }
};

} // GL_impl


struct use_GL {
    typedef GL_impl::Texture Texture;
    typedef GL_impl::DrawContext DrawContext;
};

template <class use_impl>
void f()
{
    typedef typename use_impl::Texture Texture;
    typedef typename use_impl::DrawContext DrawContext;

    Texture t;
    DrawContext ctx;
    ctx.set_texture(&t);
}

void call_f_with_gl()
{
    f<use_GL>();
}
名称空间GL\u impl{
结构纹理{
胶柄;
};
结构DrawContext{
空集_纹理(纹理*纹理)
{
glBindTexture(GL_TEXTURE_2D,纹理->句柄);
}
};
}//GL_impl
结构使用{
typedef GL_impl::纹理;
typedef GL_impl::DrawContext DrawContext;
};
样板
void f()
{
typedef typename使用_impl::纹理;
typedef typename use_impl::DrawContext DrawContext;
纹理t;
DrawContext-ctx;
ctx.set_纹理(&t);
}
无效调用\u f\u和\u gl()
{
f();
}

为什么要使纹理具有多态性?你也打算使用DirectX和软件blitting吗?为什么你需要纹理是多态的?你也打算使用DirectX和软件blitting吗?看起来不错,但我觉得set_texture()实际上不属于纹理类。此解决方案利用OpenGL是一个有状态API。如果我没有使用OpenGL,但是,例如,一个名为EggDraw的假设API,其中绘制三角形的过程是:EGG_DrawTriangle(float*顶点,EGG_TextureHandle*纹理)?所以,如果我使用那个API,我也应该把draw_triangle()方法放到纹理类中?看起来不错,但我觉得set_Texture()实际上不属于纹理类。此解决方案利用OpenGL是一个有状态API。如果我没有使用OpenGL,但是,例如,一个名为EggDraw的假设API,其中绘制三角形的过程是:EGG_DrawTriangle(float*顶点,EGG_TextureHandle*纹理)?所以,如果我使用那个API,我应该把draw_triangle()方法也放到纹理类中?