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

Template class: No appropriate default constructor avaialable. But some of my classes cannot have default constructors

本文关键字:构造函数 默认 我的 不能      更新时间:2023-10-16

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

我的意思是有些类不能有默认构造函数,因为它们有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()不是我的方法之一,它必须返回一个常量sf::Input&

您正在调用getInstance中的默认构造函数:

instance = new T;

如果有人在setInstance之前调用getInstance,你期望会发生什么?

如果在setInstance之前调用getInstance是错误的,那么如果在instance设置之前调用getInstance,则getInstance应该断言或抛出或返回NULL。只要去掉new T,你的代码就可以编译了。

如果在setInstance之前调用getInstance没有错误,那么你就没有真正的单例。早期的调用者将接收一个默认构造对象,之后的调用者将稍后获得一个集合。这是两个实例,因此不是单例。

如果你有一个引用成员,那么你就不能(明智地)使你的类默认可构造或可赋值,因为引用必须初始化,不能重新赋值。

如果需要从类中获得这些属性,则可能希望成员是一个指针,默认初始化为null,并在需要时稍后可赋值。

您可以让Singleton构造函数设置实例指针,即

Singleton::Singleton()
{
    assert(instance == nullptr);
    instance = static_cast<T*>(this);
}

你可以从接口中删除setInstance函数,getInstance可以简单地返回instance。

作为对评论的回应,我假设类是这样定义的:

class MyClassThatShouldBeASingleton : public Singleton<MyClassThatShouldBeASingleton>
{
};
当然,这意味着您需要显式地设置这样一个单例,而不是像在原始代码中那样自动实例化它。这并不一定是您想要的所有单例的工作方式,只是解决问题的一种方法。