模板类:没有合适的默认构造函数avaialable。但是我的一些类不能有默认的构造函数

时间:2011-11-08 08:17:17

标签: c++

我遇到了一个奇怪的问题,我需要为我的模板类设置一个默认构造函数,但是我想要与模板一起使用的一些类不能有默认的构造函数。

我的意思是某些类不能有默认构造函数,因为它们有一个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;

3 个答案:

答案 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>
{
};

当然,这确实意味着您需要显式设置这样的单例,而不是像原始代码那样自动实例化。这不一定是你想要所有单身人士的工作方式,只是解决问题的一种方式。