如何在这里摆脱dynamic_cast?

时间:2011-11-21 23:10:02

标签: 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(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);
    }
}

在这里使用dynamic_cast是否有意义?有没有办法避免它?

5 个答案:

答案 0 :(得分:4)

你能尝试扭转这种担忧吗?

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 DrawContext 
{ 
    virtual void set_texture(Texture* texture) = 0; 
};

class GLDrawContext : public DrawContext
{
    virtual void set_texture(Texture* texture);
};

void GLDrawContext::set_texture(Texture* texture)
{
    texture->set_texture();
}

答案 1 :(得分:2)

当然,请使用static_cast,但如果传入虚假指针,则会丢失一些错误处理。我们使用assert_cast的想法来动态调试构建和静态的发布来绕过RTTI来处理这类事情。

答案 2 :(得分:1)

我认为避免dynamic_cast的标准方法是在Texture类中添加一个虚方法:

virtual int get_texture_handle() const {return -1;}

然后仅在GLTexture类中覆盖该方法:

virtual int get_texture_handle() const {return gl_texture->handle;}

然后您的调用代码将如下所示:

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

答案 3 :(得分:0)

稍微不同的方法涉及修改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();
}

答案 4 :(得分:0)

作为替代方案,您可以尝试使用泛型来摆脱动态转换。泛型将允许您在编译时捕获错误(您永远不能将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>();
}