我在 C++ 应用程序中使用 GLFW 进行窗口和输入管理。为了将成员函数用作关键事件的回调,我按照答案 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;
}
这很不方便,原因有二:
- 从 Controller 派生的用户必须显式定义此构造函数
- 每次按下一个键都构建一个新的包装器似乎代价高昂
是否有使用此设计的替代方案?
编辑: 我最终接受了 T.C. 的提议,尽管略有不同。由于我需要子类具有它们自己的一组参数,因此能够在构造函数中提供它们是理想的。初始化单例的单独调用很容易出错,因为它可能是用错误的模板参数完成的,或者只是被遗忘了。
为了在一次调用中启用带有参数的专用对象及其对应的单例的实例化,我继续使用 CRTP,并将此构造函数添加到基类:
Controller<T>(){
T::getInstance((T*)this);
}
现在,只需一个电话,我就能得到我需要的一切:
std::shared_ptr<BaseController> c(new SMController(params_, window_));
最佳答案
实际上,我真的不明白在这里使用 CRTP 有什么意义。直接存储指向模板参数的指针有什么问题?
template <class T>
class Controller : public BC {
public:
static Controller& getInstance(T * target = nullptr){
static Controller instance(target);
return instance;
}
static void keyCallback(GLFWwindow* window, int key, int scancode,
int action, int mods){
getInstance().target_->keyCallbackImpl(window, key, scancode, action, mods);
}
private:
Controller(T* target) : target_(target) { }
//This is the wrapped input handler
T* target_;
};
关于c++ - 替代模板参数的转换构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25575057/