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

7

我有一个类,其中有一个带有以下签名的信号:

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

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

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

我有一个类"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);

但是显然这样做行不通,因为函数签名的原因。我想要做的是类似于:
// 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内部访问这些传递的参数呢?这是否可能?

2个回答

9

您的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的指针,但它确保当sender或receiver被销毁时,信号和槽连接会被移除。

使用this意味着你必须确保在删除pClassX或者pClassC之后不再发射信号。或者你可以将pClassC作为接收器,然后你必须确保pClassXpClassCpClassA仍然存活的时候仍然有效...最理想的情况是同时指定pClassXpClassC为接受器,但这是不可能的。你可以利用QPointer的保护功能来实现那一点。


谢谢,这解决了我的问题。但是我需要在捕获中使用 [&],因为那些类指针由于某种原因未被识别!我将它们放在“B类”的私有部分,所以我猜它们应该是公共的,以便在那个点上可用! - DEKKER

1

在这种情况下值得一提的一个技巧是,如果你要获取QObjects的指针,我建议首先创建QPointer变量,并在lambda中获取它们。这样,您可以检查它们是否已被删除。如果使用普通的信号和插槽,这个问题会自动处理,但是对于lambda表达式,您可能需要自己处理引用的生命周期。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接