1

ゲーム用のシンプルなグラフィックエンジンを作成しています。

これはインターフェース部分です:

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を使用するのは理にかなっていますか?それを回避する方法はありますか?

4

5 に答える 5

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();
}
于 2011-11-21T23:18:16.507 に答える
2

もちろん、代わりにstatic_castを使用してください。ただし、偽のポインタを渡すと、エラー処理が失われます。assert_castのアイデアを使用して、デバッグビルドを動的にし、リリースを静的にして、この種のRTTIを回避します。

于 2011-11-21T23:12:51.163 に答える
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);
于 2011-11-21T23:15:05.220 に答える
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();
}
于 2011-11-21T23:29:49.457 に答える
0

別の方法として、ジェネリックを使用して動的キャストを回避することもできます。Generics を使用すると、コンパイル時にエラーをキャッチできます (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>();
}
于 2011-11-22T00:06:48.697 に答える