简体   繁体   English

具有 QObject 继承的单例 - Qt

[英]Singleton with QObject inheritance - Qt

Is it possible to create singleton class with QObject inheritance?是否可以使用 QObject 继承创建单例类? I have an compilation error afer adding QObject inheritance.添加 QObject 继承后出现编译错误。 Maybe problem is in static singleton creation (should be dynamic)?也许问题在于静态单例创建(应该是动态的)? Here is my approach这是我的方法

Header标题

#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

And cpp file和cpp文件

#include "BluetoothManager.h"

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

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

}

During compilation i have an error在编译期间我有一个错误

../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;\
     ^

First, you should make your constructor(s) private, consistently with the singleton pattern intent to ensure a class only has one instance.首先,您应该将构造函数设为私有,与单例模式意图一致,以确保一个类只有一个实例。 If you let everyone build their own instance using a public constructor, you can't call your class a singleton.如果您让每个人都使用公共构造函数构建自己的实例,则不能将您的类称为单例。

Then, in your implementation, you're initializing your instance using copy-construction:然后,在您的实现中,您正在使用复制构造初始化您的实例:

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

which you can't do because QObject has deleted copy constructors (which is good, in making a singleton, after all).你不能这样做,因为QObject已经删除了复制构造函数(这很好,毕竟在制作单例时)。

Just give a default value to the constructor argument:只需给构造函数参数一个默认值:

explicit BluetoothManager(QObject * parent = nullptr);

so that your instance definition could be just:这样您的实例定义就可以是:

BluetoothManager BluetoothManager::instance; 

and the issue should be gone.这个问题应该消失了。

Also, I suggest you a quite popular variant of singleton in c++, which is well known to avoid static initialization order 'fiasco' : move the static instance from the class scope to the GetInstance function scope:另外,我建议你在 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){}
};

QObject is not copyable and you cannot call copy construction in this object, but in your static field initialization you are constructing your object and then assigning it to your static field which calls copy construction of your type. QObject不可复制并且您不能在此对象中调用复制构造,但是在您的静态字段初始化中,您正在构造您的对象,然后将其分配给您的静态字段,该字段调用您的类型的复制构造。

Instead you can use a static pointer or smart pointer and initialize it by using new .相反,您可以使用静态指针或智能指针并使用new对其进行初始化。

If your class is supposed to be a singleton class you have to define its construction private so no other code will be able to create instances of it or inherit it by using final keyword.如果你的类应该是一个单例类,你必须定义它的构造私有,这样其他代码就不能创建它的实例或使用final关键字继承它。 (making the constructor private has already done it). (使构造函数私有已经完成了)。

Yes, but the essence of Singleton is the constructor being private, so you can't create new instances of the class.是的,但 Singleton 的本质是构造函数是私有的,因此您不能创建该类的新实例。 Below is a quick and small example, but you can see a more complete one here: class PortableSettings .下面是一个快速而小巧的示例,但您可以在这里看到一个更完整的示例: class PortableSettings

bluetoothmanager.h蓝牙管理器

#ifndef BLUETOOTHMANAGER_H
#define BLUETOOTHMANAGER_H

#include <QObject>

class BluetoothManager : public QObject
{
    Q_OBJECT

public:
    static BluetoothManager* instance();

    void doSomething();

private:
    explicit BluetoothManager(QObject *parent = nullptr);

};

#endif // BLUETOOTHMANAGER_H

bluetoothmanager.cpp蓝牙管理器.cpp

#include "bluetoothmanager.h"

BluetoothManager *BluetoothManager::instance()
{
    static BluetoothManager inst;
    return &inst;
}

void BluetoothManager::doSomething()
{
    // ...
}

BluetoothManager::BluetoothManager(QObject *parent) : QObject(parent)
{
    // initialization
}

main.cpp主程序

#include <QCoreApplication>
#include "bluetoothmanager.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    BluetoothManager::instance()->doSomething();
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM