在 Qt 信号和槽中使用 lambda 语法并访问传递的参数

Using lambda syntax in Qt signal and slot and accessing passed arguments

我有一个 class 有一个带有这个签名的信号:

// CLASS A
signals:
    void requestToChangeRange(voltage_range_e vr, current_range_e cr, uint16_t bits);

还有一个 class 有这样一个插槽(注意额外的参数)

// CLASS C
public slots:
    void handleRequestRangeChange(voltage_range_e vr, current_range_e cr, uint16_t bits, uint16_t limiter);

然后我有一个 class "B" 作为所有其他 classes 的交汇点。当 class "A" 发出信号时,class "C" 应该将其重定向到 class "B"。但是 class "B" 的插槽上的那个额外参数是问题所在,因为那个额外参数来自另一个 class "X".

因此,如果 classes "A" 和 "C" 的信号和插槽匹配,我将在 class "B" 中执行以下操作:

// somewhere in CLASS B (the manager of all other classes)
connect(pClassA, &ClassA::requestToChangeRange,
    pClassC, &ClassC::handleRequestRangeChange);

但很明显,由于函数签名,这是行不通的。我想做的是:

// somewhere in CLASS B (the manager of all other classes)
connect(pClassA, &ClassA::requestToChangeRange,
this /* class B */, []() {
    // Get that last required parameter from class X
    uint16_t limiter = pClassX->getValue();
    // Call slot of class C
    pClassC->handleRequestRangeChange(vr, cr, bits, limiter);
});

那么如何访问 lambda 中传递的那些参数?这可能吗?

您的 lambda 应该知道两个对象:[pClassX, pClassC] 并接受信号的原始参数:(voltage_range_e vr, current_range_e cr, uint16_t bits).

所以你的连接应该像这样开始:

connect(pClassA, &ClassA::requestToChangeRange, this,
    [pClassX, pClassC](voltage_range_e vr, current_range_e cr, uint16_t bits) {
    //...
});

关于connect()语句中的'receiver':

连接到 lambda 时实际上不需要这个指向 QObject 的指针,但它的作用是在发送方或接收方被破坏时删除信号槽连接。

使用this意味着你必须确保在删除pClassXpClassC中的任何一个后你不再发出信号。或者你可以使用 pClassC 作为接收者,然后你必须确保 pClassX 保持有效,只要 pClassCpClassA 还活着......理想情况下你会指定pClassX AND pClassC 作为接收者,但这是不可能的。您可以为此使用 QPointer 的保护功能。

在此上下文中值得一提的一个技巧是,如果您获取指向 QObject 的指针,我建议首先创建 QPointer 变量,然后在 lambda 中获取那些。这样您就可以检查它们是否已被删除。如果您使用普通的信号和插槽,这会得到处理,但是对于 lambda,您可能需要自己处理引用的生命周期。

希望我们很快就能获得更方便的 C++ 捕获构造对象的方法。