2015-06-26 92 views
0

我正在使用OpenGL(C API)並在類中封裝了一些東西。基本上調用glGenX生成GLuint s是創建實際事物的句柄。清理時,應在這些手柄上撥打glDeleteX如何派生需要模板類型的嵌套類的模板類?

這意味着,對於我來說,有一個擁有這些類的類(以及封裝一些特定於它們的其他東西)並且能夠複製實例並將它們傳遞給它們,因此該類需要內部引用計數,以便只有在沒有更多參考時纔會調用glDeleteX

我已經做了兩次了,我正在看它的第三課。我可以看到不少我需要的課程,所以我想用模板來簡化。

下面是用引用計數的原始類的實例只在適當的時候調用glDeleteX

class Texture 
{ 
public: 
    Texture(const GLuint texture) : m_data(new Data(texture)) {} 
    Texture(const Texture& t) : m_data(t.m_data) { ++m_data->m_count; } 
    Texture(Texture&& t) : m_data(t.m_data) { ++m_data->m_count; } 
    ~Texture() { if(--m_data->m_count == 0) delete m_data; } 

    void Bind(GLenum target, GLint location) const { /* do some stuff */; 
    void Release() const { /* do some stuff */ 

    GLuint GetTexture() const { return m_data->m_texture; } 

private: 

    class Data 
    { 
    public: 
     Data(const GLuint texture) : m_count(1), m_texture(texture) {} 
     Data(const Data& data) : m_count(1), m_texture(data.m_texture) {} 
     ~Data() { glDeleteTexture(1,&m_texture); } 

     GLuint m_texture; 
     unsigned int m_count; 
    }; 

    Data* m_data; 
}; 

這是我嘗試在templatizerating它:

template<typename... Ts> 
class ReferenceCountedObject 
{ 
public: 

    ReferenceCountedObject(const Ts... args) 
    : 
     m_data(new Data(args...)) 
    {} 

    ReferenceCountedObject(const ReferenceCountedObject& h) 
    : 
     m_data(h.m_data) 
    { 
     ++m_data->m_count; 
    } 

    ReferenceCountedObject(ReferenceCountedObject&& h) 
    : 
     m_data(h.m_data) 
    { 
     ++m_data->m_count; 
    } 

    virtual ~ReferenceCountedObject() 
    { 
     if(--m_data->m_count == 0) 
      delete m_data; 
    } 

protected: 

    class Data 
    { 
    public: 

     Data(const Ts... args) 
     : 
      m_count(1), 
      m_dataMembers(args...) 
     { 
     } 

     Data(const Data& data) 
     : 
      m_count(1), 
      m_dataMembers(data.m_dataMembers) 
     { 
     } 

     virtual ~Data() 
     { 
      std::cout << "deleting base" << std::cout; 
     } 

     std::tuple<Ts...> m_dataMembers; 
     unsigned int m_count; 
    }; 

    Data* m_data; 
}; 

的想法是,內部Data類可能只需要一個GLuint句柄Texture類,但它可能需要三個不同的另一種類型。所以,這就是爲什麼有內部tuple

現在,我有問題。這是我的原班現在從這個模板化類派生:

class Texture : public ReferenceCountedObject<GLuint> 
{ 
public: 
    Texture(GLuint texture) : ReferenceCountedObject(texture) {} 

    Texture(const Texture& t) : ReferenceCountedObject(t) {} 

    Texture(Texture&& t) : ReferenceCountedObject(t) {} 

    void Bind(GLenum target, GLint location) const { /* does that stuff */} 
    void Release() const { /* does that stuff */ } 

    GLuint GetTexture() const { return std::get<0>(m_data->m_dataMembers); } 

protected: 
}; 

我如何定義的基類Data的析構函數?到目前爲止,我已經試着這樣做:

更改基類的一個位:

template<class DataType, typename... Ts> 
class ReferenceCountedObject 
{ 
    /* ... */ 
protected: 
    DataType* m_data; 
}; 

所以這種方式可以提供數據類型,只是重寫虛析構函數:

class Texture : public ReferenceCountedObject<Texture::TData,GLuint> 
{ 
    /* ... */ 
protected: 
    class TData : public ReferenceCountedObject::Data 
    { 
    public: 
     ~TData() 
     { 
      std::cout << "deleting derived" << std::cout; 
      glDeleteTextures(1,&std::get<0>(m_dataMembers)); 
     }; 
    }; 
} 

但我不能實例化ReferenceCountedObjectTexture::TData,因爲TData是我想要定義的一部分。

我該如何正確地做到這一點?我承認我可以用完全不正確的方式解決這個問題。

回答

1

爲什麼不只是使用shared_ptr?這也是參考數字,而且更容易傳遞。你的類只需要處理分配和釋放紋理,並且shared_ptr在正確的時間執行了refcounting和自動刪除操作。另外,這可以讓你免費使用弱指針。

你可以定義內部Texture類,然後做

typedef std::shared_ptr<internal::Texture> Texture; 

使外部用戶永遠只能使用引用計數的紋理。

+0

我知道我可以。事實上,這正是我之前所做的。但我更願意弄清楚如何做到上述。 – NeomerArcana

+0

而不是參數化您的refcounted類的數據類型,通過包含類(它具有所有必要的獲取/發佈邏輯)對其進行參數化。你會發現實現起來要容易得多。 – nneonneo