Wie kann ich hier einen dynamic_cast loswerden?

  • Ich mache eine einfache Grafik-Engine für mein Spiel.

    Dies ist ein Schnittstellenteil:

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

    Dies ist Implementierungsteil:

     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);
        }
    }
     
    < Ist es sinnvoll, dynamic_cast hier zu verwenden? Gibt es eine Möglichkeit, dies zu vermeiden?

    22 November 2011
    lamefun
5 answers
  • Könnten Sie versuchen, die Bedenken aufzuheben?

     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();
    }
     
    22 November 2011
    Adam MarasLulu
  • Verwenden Sie stattdessen static_cast. Wenn Sie jedoch einen falschen Zeiger übergeben, gehen einige Fehler bei der Fehlerbehandlung verloren. Wir verwenden eine assert_cast-Idee, um beim Debuggen von Builds dynamisch zu sein, und static for release, um die RTTI für diese Art von Dingen zu umgehen

    22 November 2011
    Michael Dorgan
  • Ich denke, der übliche Weg, einen Dynamic_cast zu vermeiden, wäre das Hinzufügen einer virtuellen Methode zur Texture-Klasse:

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

    Dann überschreiben Sie die Methode nur in Ihrer GLTexture-Klasse:

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

    Dann würde Ihr aufrufender Code funktionieren sehen Sie so aus:

     int handle = texture->get_texture_handle();
    if (handle >= 0) glBindTexture(GL_TEXTURE_2D, handle);
     
    22 November 2011
    Jeremy Friesner
  • Eine etwas andere Methode, bei der die Texturklasse geändert wird.

     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();
    }
     
    22 November 2011
    Carl
  • Alternativ können Sie versuchen, Generics zu verwenden, um den dynamischen Cast zu umgehen. Mit Generics können Sie Fehler beim Kompilieren abfangen (Sie können niemals eine DirectX-Textur an einen GL DrawContext übergeben). Außerdem fallen keine Kosten für die dynamische Übermittlung an, und der Compiler sollte Inlining ausführen können.

     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>();
    }
     
    22 November 2011
    Bowie Owens