YOU0324 2025-08-28 09:31 采纳率: 60%
浏览 6
已结题

QT C++ lambda表达式多次断开与链接

#ifndef CONNECTIONMANAGER_H
#define CONNECTIONMANAGER_H

#include <QObject>
#include <vector>
#include <functional>   // 必须包含,支持 std::function
#include <QMetaObject>  // 包含 QMetaObject::Connection

class ConnectionManager : public QObject
{
    Q_OBJECT


private:
    using ConnectFunction = std::function<QMetaObject::Connection()>;

    // 存储:创建连接的函数 + 当前连接对象
    std::vector<std::pair<ConnectFunction, QMetaObject::Connection>> m_connections;
public:
    // 定义:创建连接的函数(无参,返回新的连接对象)

    explicit ConnectionManager(QObject *parent = nullptr);

    // 添加需要管理的连接(传入“创建连接”的逻辑)
    void addConnection(ConnectFunction connectFunc);

    // 断开所有管理的连接
    void disconnectAll();

    // 重新连接所有管理的连接(先断旧连接,再创建新连接)
    void reconnectAll();

    // 清空连接(断开 + 清除列表)
    void clear();
};


// 自动守卫类(RAII:函数进入时断开,退出时重连)
class ConnectionGuard
{
public:
    explicit ConnectionGuard(ConnectionManager& manager);
    ~ConnectionGuard();

    // 禁止拷贝(避免重复管理连接)
    ConnectionGuard(const ConnectionGuard&) = delete;
    ConnectionGuard& operator=(const ConnectionGuard&) = delete;

private:
    ConnectionManager& m_manager;
};

#endif // CONNECTIONMANAGER_H
#include "connectionmanager.h"

ConnectionManager::ConnectionManager(QObject *parent)
    : QObject(parent)
{
}

void ConnectionManager::addConnection(ConnectFunction connectFunc)
{
    if (connectFunc) { // 检查函数对象有效
                       // 立即创建连接,并存储“创建函数 + 连接对象”
        m_connections.emplace_back(connectFunc, connectFunc());
    }
}

void ConnectionManager::disconnectAll()
{
    // 遍历所有连接,断开(VS2015 不支持结构化绑定,改用 pair 访问)
    for (auto& pair : m_connections) {
        ConnectFunction& createFunc = pair.first;            // 创建连接的函数
        QMetaObject::Connection& conn = createFunc();        // 测试中pair.second在传递中会被其他未知行为改变地址
        QObject::disconnect(conn);                            // Qt 支持重复断开,安全无副作用
    }
}

void ConnectionManager::reconnectAll()
{
    for (auto& pair : m_connections) {
        ConnectFunction& createFunc = pair.first;            // 创建连接的函数
        QMetaObject::Connection& conn = pair.second;        // 当前连接对象

         // 先断开旧连接(若存在)
        QObject::disconnect(conn);
        // 重新执行创建逻辑,生成新连接
        if (createFunc) {
            conn = createFunc();
        }
    }
}

void ConnectionManager::clear()
{
    disconnectAll();
    m_connections.clear();
}


ConnectionGuard::ConnectionGuard(ConnectionManager& manager)
    : m_manager(manager)
{
    m_manager.disconnectAll();            // 构造时自动断开连接
}

ConnectionGuard::~ConnectionGuard()
{
    m_manager.reconnectAll();            // 析构时自动重连连接
}

定义:

connManager->addConnection([this]() {
        return  QObject::connect(m_tblCentPad1, &QTableWidget::itemChanged, this, [=](QTableWidgetItem *item) {
            if (item) {
                JudgeTableLimit(1, item);
            }
        });
    });

使用:

ConnectionGuard guard(*connManager);

功能 :在一个函数执行中先断开lambda表达式的connect链接 在函数执行完之后在链接上
问题:无法断开lambda链接还是会触发信号

  • 写回答

4条回答 默认 最新

  • YOU0324 2025-08-28 10:03
    关注

    已解决,在使用过程中槽函数触发比较混乱,确保当前函数内部不会有重复触发当前函数的信号

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 9月5日
  • 已采纳回答 8月28日
  • 创建了问题 8月28日