2014-02-14 4 views
1

저는 현재 제 자신의 엔진, 특히 그래픽 인터페이스에서 작업 중이며 DirectX와 OpenGL 렌더링 중 하나를 선택할 수 있도록 노력하고 있습니다. 이 목적을 위해 Texture Manager 싱글 톤을 원합니다 (저는이 표준 구현을 사용하는 데 익숙합니다). 그러나이 경우에는 기능을 추상화하는 동안 인스턴스의 동적 유형을 선택할 수 있기를 원합니다. 당신이 볼 수 있듯이, 나는 싱글의 RAII 보너스를 희생하고 null로 m_pInstance 포인터를 초기화 할 필요했습니다템플릿 유형이있는 동적 유형 Singleton입니다. 이것이 가능한 접근법입니까? [Solution provided]

template <typename T> 
class TextureManagerType 
{ 
public: 

    virtual ~TextureManagerType() = 0 {} 


    T* GetTexture(TEXTURE_ID texID) 
    { 
     std::map<TEXTURE_ID, T*>::const_iterator it = m_textures.find(texID); 
     if(it != m_textures.end()) 
     { 
      return (*it)->second; 
     } 
     else 
     { 
      assert(0); 
      return 0; 
     } 
    } 

    bool Load(const std::string& texturePaths) 
    { 
     File f; 
     if(!f.Open(texturePaths)) 
     { 
      ReportError("Fatal error! Could not open: " + texturePaths); 
      return false; 
     } 

     std::string str; 

     while(!f.EndOf()) 
     { 
      if(!f.GetString(&str)) 
      { 
       ReportError("Warning: Unexpected end of file in  texturepaths file: " + texturePaths); 
      } 
      LoadTexture(str); 
     } 

     return true; 
    } 

    virtual T* LoadTexture(const std::string& texturePath) = 0; 

protected: 
    std::map<TEXTURE_ID, T*> m_textures; 
}; 


//Uncopyable is a base class with a disabled copy constructor 
class TextureManager : public Uncopyable 
{ 
private:  
    TheTextureManager(); 

public: 
//T here is underlined in all three mentions as it is undefined 
    static TextureManagerType<T>* Instance() 
    { 
     return m_pInstance; 
    } 
    static void SetDynamicType(TextureManagerType<T>* type) 
    { 
     m_pInstance = type; 
    } 
    static TextureManagerType<T>* m_pInstance; 


    //static TexManagerType* Instance() 
    //{ 
    // return m_pInstance; 
    //} 
    //static void SetDynamicType(TexManagerType* type) 
    //{ 
    // m_pInstance = type; 
    //} 
    //static TexManagerType* m_pInstance; 

}; 

//Named to be consistent with normal singletons 
typedef TextureManager TheTextureManager; 

: 여기에 지금까지 내 구현입니다. 전 세계 접근성을 유지하면서 각 파생 관리자의 수명을 제어 할 수 있도록하고 싶습니다으로

//I want the singleton once set, to be able to be accessed thusly: 
TheTextureManager::Instance()->DoTextureFunction(); 

나는 TextureManager의 각 유형에 대한 싱글을 원하지 않는다. 현재 TextureManager :: Instance의 반환 값 유형은 액세스 할 수없는 템플릿 형식을 알아야하므로 내 시스템이 전혀 작동하지 않습니다.

TextureManager 내에서 TextureManagerType을 중첩하려고했으나 텍스처 관리자에 을 호출 할 때마다 필요한 유형이 템플릿 추출 매개 변수로 필요하다는 것을 의미했습니다.

여러분의 의견을지지 해 주시기 바랍니다. 중요/모든 세부 사항을 빠뜨린 경우 문의하십시오. 브레인은 지금도 생각하기에는 너무 지쳤습니다.

+0

텍스처 관리자에서 설정 한 TexManagerType은 어떻게 결정합니까? –

+0

내 Direct X Renderer 클래스에서 TextureManager :: SetDynamicType (new DXTextureManager)을 호출 할 것입니다 – Crackerjack55

+0

한 번에 둘 이상의 유형을 사용할 수 있습니까? –

답변

1

TextureManagerType에 대해 템플릿 기반이 아닌 추상 인터페이스를 정의한 다음이를 사용하여 텍스처 관리자 싱글 톤 객체에서 텍스처 관리자 구현을 참조 할 수 있습니다.
이렇게하려면 텍스처 형식의 개체에 대한 다형성 표현이 필요합니다.이 형식은 유니온 형식처럼 단순한 것일 수도 있고 추상 기본 클래스이며 다른 구체적인 질감 유형에 대한 파생 클래스가 될 수도 있습니다.
그것은 모두 같이 보일 수 있습니다

조금 거친, 그러나 희망 당신은 아이디어를 얻을
union TextureContainer { 
    OpenGLTexture* oglt; 
    DirectXTexture* dxt; 
}; 

class TextureManagerTypeBase 
{ 
public: 

    virtual ~TextureManagerType() = 0; 
    virtual TextureContainer GetTexture(TEXTURE_ID texID) = 0; 
    virtual TextureContainer LoadTexture(const std::string& texturePath) = 0; 

    //this looks like it only refers to other public 
    // methods, so it's staying here 
    virtual bool Load(const std::string& texturePaths) 
    { 
    ... 
    } 
}; 

template <typename T> 
class TextureManagerType : public TextureManagerTypeBase 
{ 
public: 
    // pretty much the same as before 
    // minus Load wich is defined in the base class 
    // plus wrapping T into a TextureContainer 
    ... 
}; 


//Uncopyable is a base class with a disabled copy constructor 
class TextureManager : public Uncopyable 
{ 
private:  
    TheTextureManager(); 

public: 
//T here is underlined in all three mentions as it is undefined 
    static TextureManagerTypeBase* Instance() 
    { 
     return m_pInstance; 
    } 
    static void SetDynamicType(TextureManagerTypeBase* type) 
    { 
     m_pInstance = type; 
    } 
    static TextureManagerTypeBase* m_pInstance; 
}; 

.

+0

그게 좋습니다! DirectX 렌더러가 활성화되어있을 때 리턴 코드가 올바르지 않아 반환 유형이 달라 지길 원하지 않는다는 것을 알고 난 후에이 침대에 앉아서 침대에있을 때를 알았습니다. 또한 노조를 실험 해 볼만한 이유가 생겼습니다. 힘내 친구 야! – Crackerjack55

+0

당신이 좋아하는 것을 기쁘게 생각합니다! 그러나 본질적으로 이것은 void *를 반환하고 클라이언트 코드에서 필요에 따라 형변환하는 것과 거의 같습니다. 서브 클래 싱하지 않고 더 좋은 옵션은 boost :: variant (http://www.boost.org/doc/libs/1_55_0/doc/html/variant.html) –

+0

을 사용하는 것입니다. 신난다. 내가 익숙해지기를 원하는 주제의 2 층 더미에있는 것). 나는 평판 포인트를 얻었다면 당신의 대답을 높일 것입니다. 정말 그 얼굴 손바닥으로 일해야합니다. – Crackerjack55