具有 QObject 继承的单例 - Qt

s.p*_*zko 2 c++ qt

是否可以使用 QObject 继承创建单例类?添加 QObject 继承后出现编译错误。也许问题在于静态单例创建(应该是动态的)?这是我的方法

标题

#ifndef BLUETOOTHMANAGER_H
#define BLUETOOTHMANAGER_H

#include <QObject>

class BluetoothManager : public QObject
{
    Q_OBJECT
public:
    virtual ~BluetoothManager() {}

    /// Static getter
    static BluetoothManager & GetInstance()
    {
        return instance;
    }

private:
    /// static Bluetooth manager instance
    static BluetoothManager instance;

    explicit BluetoothManager(QObject * parent);
};

#endif // BLUETOOTHMANAGER_H
Run Code Online (Sandbox Code Playgroud)

和cpp文件

#include "BluetoothManager.h"

/// singleton creation
BluetoothManager BluetoothManager::instance = BluetoothManager(static_cast<QObject*>(nullptr));

BluetoothManager::BluetoothManager(QObject * parent)
    : QObject(parent)
{

}
Run Code Online (Sandbox Code Playgroud)

在编译期间我有一个错误

../QtHealthApp/network/bluetooth/BluetoothManager.cpp:4:94: error: use of deleted function ‘BluetoothManager::BluetoothManager(const BluetoothManager&)’  BluetoothManager BluetoothManager::instance = BluetoothManager(static_cast<QObject*>(nullptr));
                                                                                              ^ In file included from /opt/Qt5.12.LTS/5.12.6/gcc_64/include/QtCore/qnamespace.h:43:0,
                 from /opt/Qt5.12.LTS/5.12.6/gcc_64/include/QtCore/qobjectdefs.h:48,
                 from /opt/Qt5.12.LTS/5.12.6/gcc_64/include/QtCore/qobject.h:46,
                 from /opt/Qt5.12.LTS/5.12.6/gcc_64/include/QtCore/QObject:1,
                 from ../QtHealthApp/network/bluetooth/BluetoothManager.h:4,
                 from ../QtHealthApp/network/bluetooth/BluetoothManager.cpp:1: ../QtHealthApp/network/bluetooth/BluetoothManager.h:33:20: note: declared here
     Q_DISABLE_COPY(BluetoothManager)
                    ^ /opt/Qt5.12.LTS/5.12.6/gcc_64/include/QtCore/qglobal.h:372:5: note: in definition of macro ‘Q_DISABLE_COPY’
     Class(const Class &) Q_DECL_EQ_DELETE;\
     ^
Run Code Online (Sandbox Code Playgroud)

p-a*_*l-o 5

首先,您应该将构造函数设为私有,与单例模式意图一致,以确保一个类只有一个实例。如果您让每个人都使用公共构造函数构建自己的实例,则不能将您的类称为单例。

然后,在您的实现中,您正在使用复制构造初始化您的实例:

BluetoothManager BluetoothManager::instance = BluetoothManager(static_cast<QObject*>(nullptr));
Run Code Online (Sandbox Code Playgroud)

你不能这样做,因为QObject已经删除了复制构造函数(这很好,毕竟在制作单例时)。

只需给构造函数参数一个默认值:

explicit BluetoothManager(QObject * parent = nullptr);
Run Code Online (Sandbox Code Playgroud)

这样您的实例定义就可以是:

BluetoothManager BluetoothManager::instance; 
Run Code Online (Sandbox Code Playgroud)

这个问题应该消失了。

另外,我建议你在 C++ 中使用一个非常流行的单例变体,众所周知,它可以避免静态初始化顺序 'fiasco':将静态实例从类作用域移动到GetInstance函数作用域:

class BluetoothManager : public QObject
{
    Q_OBJECT
public:

    virtual ~BluetoothManager() {}

    /// Static getter
    static BluetoothManager & GetInstance()
    {
        static BluetoothManager instance;
        return instance;
    }

private:
    explicit BluetoothManager(QObject * parent = nullptr){}
};
Run Code Online (Sandbox Code Playgroud)