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

DEK*_*KER 4 c++ lambda qt signals-slots c++11

我有一个带有此签名信号的类:

// CLASS A
signals:
    void requestToChangeRange(voltage_range_e vr, current_range_e cr, uint16_t bits);
Run Code Online (Sandbox Code Playgroud)

还有另一个类具有这样的插槽(请注意额外的参数)

// CLASS C
public slots:
    void handleRequestRangeChange(voltage_range_e vr, current_range_e cr, uint16_t bits, uint16_t limiter);
Run Code Online (Sandbox Code Playgroud)

然后我有一个班级“ B”,它是所有其他班级的集合点。当类“ A”发出信号时,类“ C”应将其重定向到类“ B”。但是,类“ B”的插槽上的该额外参数是问题,因为该额外参数来自另一个类“ X”。

因此,如果类别“ A”和“ C”的信号和插槽匹配,我将在类别“ B”中执行以下操作:

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

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

// 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);
});
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*ngs 5

您的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) {
    //...
});
Run Code Online (Sandbox Code Playgroud)

关于connect()语句中的“接收器”:

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

使用this意味着您必须确保删除其中一个后pClassXpClassC不再发出信号。另外,您也可以将其pClassC用作接收器,然后必须确保它pClassX一直有效pClassCpClassA一直存在。...理想情况下,您将pClassXAND 指定pClassC为接收器,但这是不可能的。您可以QPointer为此使用a的保护功能。