如何摆脱这里的dynamic_cast?

发布于 2024-12-17 14:03:34 字数 578 浏览 1 评论 0原文

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

这是接口部分:

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 有意义吗?有办法避免吗?

I'm making a simple graphics engine for my game.

This is interface part:

class Texture { ... };

class DrawContext 
{ 
    virtual void set_texture(Texture* texture) = 0; 
}

This is implementation part:

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);
    }
}

Does it make sense to use dynamic_cast here? Is there a way to avoid it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

等待圉鍢 2024-12-24 14:03:34

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

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

Could you try reversing the concern?

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();
}
獨角戲 2024-12-24 14:03:34

当然,可以使用 static_cast 来代替,但如果传入一个虚假指针,您将失去一些错误处理能力。我们使用assert_cast的想法来动态调试构建和静态发布来绕过RTTI来处理这类事情。

Sure, use static_cast instead, though you will lose some error handling if you pass in a bogus pointer. We use an assert_cast idea to dynamic on debug builds and static for release to get around the RTTI for this sort of thing.

初吻给了烟 2024-12-24 14:03:34

我认为避免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);

I think the standard way to avoid a dynamic_cast would be to add a virtual method to the Texture class:

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

Then override the method only in your GLTexture class:

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

Then your calling code would look like this:

int handle = texture->get_texture_handle();
if (handle >= 0) glBindTexture(GL_TEXTURE_2D, handle);
故事还在继续 2024-12-24 14:03:34

稍微不同的方法涉及修改纹理类。

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

A slightly different approach that involves modifying the Texture class.

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();
}
温柔女人霸气范 2024-12-24 14:03:34

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

As an alternative you could try using generics to get away from dynamic cast. Generics will let you catch errors at compile time (you can never pass a DirectX texture to a GL DrawContext). Additionally, there will be no cost for dynamic dispatch and the compiler should be able to do inlining.

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>();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文