Reputation: 4232
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?
Upvotes: 2
Views: 501
Reputation: 2976
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>();
}
Upvotes: 0
Reputation: 44448
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();
}
Upvotes: 0
Reputation: 26853
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();
}
Upvotes: 4
Reputation: 73081
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);
Upvotes: 2
Reputation: 12515
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.
Upvotes: 2