一、什么是单例?

单例 = 整个程序里,这个类永远只有 1 个对象,永远不会创建第二个。

就像:

  • 一个公司只有 1 个老板
  • 一个程序只有 1 个配置管理
  • 一个软件只有 1 个日志管理器
  • 一个项目只有 1 个数据库连接

你不管在哪里调用,拿到的都是同一个实例。


二、为什么要用单例?(Qt 里最常见场景)

在 Qt 开发中,单例几乎必用,原因:

  1. 全局共享数据(配置、用户信息、主题、日志)
  2. 避免重复创建资源(数据库、网络、串口、文件)
  3. 全局统一调用(任何页面都能直接用,不用传对象)
  4. 防止多份实例导致数据错乱、冲突

三、单例的核心特点(记住这 4 点就够)

  1. 构造函数私有化 → 不让外面随便 new
  2. 提供一个静态获取实例的方法(如 instance())
  3. 全局唯一 → 永远只有一个对象
  4. 线程安全可选(Qt 常用)

四、Qt 中最标准、最常用的单例写法(直接复制用)

这是工业级写法,线程安全 + 懒加载 + 无法外部创建。

1. 头文件 (.h)

cpp

运行

#ifndef CONFIGMANAGER_H
#define CONFIGMANAGER_H

#include <QObject>

class ConfigManager : public QObject
{
    Q_OBJECT

public:
    // 唯一获取实例的接口(全局只有这一个对象)
    static ConfigManager& instance();

    // 示例:你可以加自己的函数/变量
    void setValue(const QString& key, const QVariant& value);
    QVariant getValue(const QString& key);

private:
    // 私有化构造!重点!外部不能 new
    explicit ConfigManager(QObject *parent = nullptr);

    // C++ 禁止拷贝和赋值(保证单例不被复制)
    ConfigManager(const ConfigManager&) = delete;
    ConfigManager& operator=(const ConfigManager&) = delete;

private:
    // 自己的成员变量
    QVariantMap m_configData;
};

#endif // CONFIGMANAGER_H

2. 源文件 (.cpp)

cpp

运行

#include "ConfigManager.h"

// 获取单例实例
ConfigManager& ConfigManager::instance()
{
    // static 保证只会创建一次
    static ConfigManager s_instance;
    return s_instance;
}

// 构造函数私有化
ConfigManager::ConfigManager(QObject *parent)
    : QObject(parent)
{
}

// 示例方法
void ConfigManager::setValue(const QString& key, const QVariant& value)
{
    m_configData[key] = value;
}

QVariant ConfigManager::getValue(const QString& key)
{
    return m_configData.value(key);
}

五、怎么使用?(任何地方都能直接调用)

cpp

运行

// 不需要 new!不需要指针!直接用!
ConfigManager::instance().setValue("ip", "192.168.1.1");
QString ip = ConfigManager::instance().getValue("ip").toString();

不管你在 MainWindow、弹窗、子页面、工具类里调用,拿到的永远是同一个对象。


六、最关键的一句话总结

单例就是:一个类,整个程序只造一个对象,到处共用,不能复制,不能随便新建。


七、Qt 里常见的单例用途

  • 配置管理 ConfigManager
  • 日志管理 LogManager
  • 数据库管理 DbManager
  • 串口 / 网络管理 SerialPort
  • 全局主题 / 样式 ThemeManager
  • 共享数据传递(替代全局变量)

八、你可能会问的问题

1. 单例和全局变量有什么区别?

  • 全局变量:不安全、可被随意修改、没有封装
  • 单例:安全、可控、只能通过接口访问、唯一实例

2. 这个写法线程安全吗?

在 C++11 及以上是安全的,Qt 5/6 都满足。

3. 单例可以用在 QML 里吗?

可以!注册到 QML 上下文就能在 QML 里当全局单例用。


总结

  • 单例 = 全局唯一实例
  • 禁止外部创建、禁止拷贝
  • static instance () 是唯一入口
  • Qt 开发几乎必用,用于共享资源、全局管理
  • 上面的代码直接复制就能用

 本人电子信息工程专业,工作逼迫写qt软件,一步一步学习qt,从非软件专业视角学习qt,遇到很多奇葩问题,请关注微信公众号。

更多推荐