我遇到了一个奇怪的问题,我需要为我的模板类设置一个默认构造函数,但是我想要与模板一起使用的一些类不能有默认的构造函数。
我的意思是某些类不能有默认构造函数,因为它们有一个const引用字段,因此,它们必须在构造函数/初始化列表中设置。如果我有一个默认构造函数,则没有任何东西可以设置这些引用。
所以,我想有两种可能的解决方案:有时候在模板类中找到一种允许非默认构造函数的方法,或者找到一种在默认构造函数中设置const引用字段的方法。
如何解决此问题?
这是我的模板代码:
#pragma once
template<class T>
class Singleton
{
public:
static T* getInstance()
{
if(!instance) instance = new T;
return instance;
}
static void setInstance(T* inst)
{
instance = inst;
}
protected:
Singleton();
~Singleton();
private:
Singleton(Singleton const&);
Singleton& operator=(Singleton const&);
static T* instance;
};
template<class T> T* Singleton<T>::instance = 0;
这里是我设置const引用的地方(在.cpp中):
InputHandler::InputHandler(const sf::Input& inputObject)
: input(inputObject)
{
输入在标题中定义:
const sf::Input& input;
由于这段代码(在不同的文件中),我必须使用常量引用:
const sf::Input& input = window.GetInput();
InputHandler* inputHandler = new InputHandler(input);
Singleton<InputHandler>::setInstance(inputHandler);
GetInput()不是我的方法之一,它必须返回一个const sf :: Input&amp;
答案 0 :(得分:2)
如果你有一个引用成员,那么你不能(理智地)使你的类默认可构造或可赋值,因为引用必须初始化,并且不能重新分配。
如果你需要类中的那些属性,那么你可能希望该成员是一个指针,默认情况下初始化为null,如果需要可以在以后分配。
答案 1 :(得分:2)
您正在使用以下函数调用getInstance中的默认构造函数:
instance = new T;
如果有人在setInstance之前调用getInstance,你会发生什么?
如果在setInstance之前调用getInstance是一个错误,那么在设置实例之前调用时,getInstance应该断言或抛出或返回NULL。只需删除new T
,您的代码就会编译。
如果在setInstance之前调用getInstance不是错误,那么你真的没有单例。早期的调用者将收到一个默认的构造对象,稍后调用者将获得一个稍后的集合。这是两个实例,因此不是单身。
答案 2 :(得分:1)
你也许可以让Singleton构造函数设置实例指针,即
Singleton::Singleton()
{
assert(instance == nullptr);
instance = static_cast<T*>(this);
}
然后,您可以从界面中删除setInstance函数,getInstance可以只返回实例。
在回应评论时,我假设课程的定义如下:
class MyClassThatShouldBeASingleton : public Singleton<MyClassThatShouldBeASingleton>
{
};
当然,这确实意味着您需要显式设置这样的单例,而不是像原始代码那样自动实例化。这不一定是你想要所有单身人士的工作方式,只是解决问题的一种方式。