我正在使用GLFW進行C++應用程序中的窗口和輸入管理。爲了使用成員函數作爲關鍵事件的回調函數,我按照答案here中的建議使用了單例。替代模板參數的轉換構造函數
但是,我需要實現不同的輸入處理程序。我的方法是使用Singleton作爲實際輸入處理程序(controller_)的包裝以允許多態。但是,爲了實例化Singleton,基類不能是抽象的。該解決方案涉及使用CRTP以便能夠從基類的實現中調用特定的輸入處理方法。
template <class T>
class Controller : public BC{ //BC is just for using this class as a template parameter itself
public:
Controller(){}
Controller(Controller &controller){
controller_ = &controller;
}
static Controller& getInstance(Controller *controller){
static Controller instance(*controller);
return instance;
}
//This is the key move, where the concrete implementation is invoked.
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods){
Controller *aux;
(static_cast<T>(getInstance(aux))).keyCallbackImpl(window, key, scancode, action, mods);
}
//Stub to be overridden by the concrete input handler
virtual void keyCallbackImpl(GLFWwindow* window, int key, int scancode, int action, int mods){}
//This is the wrapped input handler
Controller *controller_;
};
這工作正常。但是,派生類存在問題。爲了能夠執行轉換,我必須定義一個轉換構造函數。
SMController(Controller<SMController> &c){
controller_ = c.controller_;
std::cout << "Constructor" << std::endl;
}
這是不方便的,原因有二:
- 用戶從控制器導出必須明確定義這個構造
- 新包裝的每一個鍵被按下時的建築似乎昂貴
使用這種設計有沒有替代這種轉換?
編輯: 我結束了與T.C.的提案,但略有不同。由於我需要具有自己的一組參數的子類,因此能夠在構造函數中提供它們是理想的。初始化單例的單獨調用很容易出錯,因爲它可以用錯誤的模板參數完成,或者只是被遺忘。
爲了使與它的參數,並且在一個呼叫其對應的單專門對象的實例化,我不停使用CRTP和我加入此構造基類:現在
Controller<T>(){
T::getInstance((T*)this);
}
,與只需一個電話我就可以得到我需要的一切:
std::shared_ptr<BaseController> c(new SMController(params_, window_));
對不起,如果aux未初始化,getInstance(aux)應該如何工作?我錯過了什麼嗎? – 2014-08-29 19:45:08
單例是靜態的,所以它僅在第一次調用'getInstance()'時被實例化(這是在別處完成的)。 – broncoAbierto 2014-08-29 19:49:36
典型的CRTP實現從'Base *'到'T *'或'* this'從'Base &'到'T&'投射'this'。 –
2014-08-29 20:01:43