Qt信号可以返回一个值吗?

Mar*_*utz 51 c++ qt return-value signals-slots boost-signals

Boost.Signals允许使用槽的返回值的各种策略来形成信号的返回值.例如,添加它们,形成vector它们,或返回最后一个.

常见的智慧(在Qt文档中表达[编辑:以及该问题的一些答案])是Qt信号不可能有这样的事情.

但是,当我在以下类定义上运行moc时:

class Object : public QObject {
    Q_OBJECT
public:
    explicit Object( QObject * parent=0 )
        : QObject( parent ) {}

public Q_SLOTS:
    void voidSlot();
    int intSlot();

Q_SIGNALS:
    void voidSignal();
    int intSignal();
};
Run Code Online (Sandbox Code Playgroud)

不仅没有moc抱怨具有非void返回类型的信号,它似乎以允许返回值传递的方式主动实现它:

// SIGNAL 1
int Object::intSignal()
{
    int _t0;
    void *_a[] = { const_cast<void*>(reinterpret_cast<const void*>(&_t0)) };
    QMetaObject::activate(this, &staticMetaObject, 1, _a);
    return _t0;
}
Run Code Online (Sandbox Code Playgroud)

所以:根据文档,这件事是不可能的.那么moc在这做什么?

插槽可以有返回值,那么我们可以将带有返回值的插槽连接到具有返回值的信号吗?毕竟,这可能吗?如果是这样,它有用吗?

编辑:我不是要求解决方法,所以请不要提供任何解决方法.

编辑:它显然在Qt::QueuedConnection模式中没用(QPrintPreviewWidget API也不是,但它仍然存在并且很有用).但是什么Qt::DirectConnectionQt::BlockingQueuedConnection(或者Qt::AutoConnection,当它解决时Qt::DirectConnection).

jsh*_*rer 38

好.所以,我做了一些调查.似乎这是可能的.我能够发出信号,并从信号连接的插槽中接收值.但是,问题是它只返回多个连接插槽的最后一个返回值:

这是一个简单的类定义(main.cpp):

#include <QObject>
#include <QDebug>

class TestClass : public QObject
{
    Q_OBJECT
public:
    TestClass();

Q_SIGNALS:
    QString testSignal();

public Q_SLOTS:
    QString testSlot1() {
        return QLatin1String("testSlot1");
    }
    QString testSlot2() {
        return QLatin1String("testSlot2");
    }
};

TestClass::TestClass() {
    connect(this, SIGNAL(testSignal()), this, SLOT(testSlot1()));
    connect(this, SIGNAL(testSignal()), this, SLOT(testSlot2()));

    QString a = emit testSignal();
    qDebug() << a;
}

int main() {
    TestClass a;
}

#include "main.moc"
Run Code Online (Sandbox Code Playgroud)

主运行时,它构造一个测试类.构造函数将两个插槽连接到testSignal信号,然后发出信号.它从被调用的槽中捕获返回值.

不幸的是,您只能获得最后的返回值.如果你评估上面的代码,你会得到:"testSlot2",来自信号连接槽的最后一个返回值.

这就是原因.Qt信号是信令模式的语法糖界面.插槽是信号的接收者.在直接连接的信号槽关系中,您可以将其视为(伪代码):

foreach slot in connectedSlotsForSignal(signal):
    value = invoke slot with parameters from signal
return value
Run Code Online (Sandbox Code Playgroud)

显然,moc在这个过程中做了一点帮助(基本类型检查等),但这有助于绘制图片.

  • 如果所有内容都在同一个线程上,它将起作用,因为您将在插槽上进行同步函数调用.如果您有一个多线程应用程序,则该调用将是异步的,并且不具有返回值. (4认同)
  • 谢谢你真的尝试:)我已经编辑你的代码更简单,更短.然而,问题仍然存在:如果它起作用(具有"最后调用的"语义),为什么文档说它没有? (2认同)

vin*_*nes 8

不,他们不能.

Boost::signals与Qt中的完全不同.前者提供了高级回调机制,而后者实现了信令习惯用法.在多线程环境中,Qt(交叉线程)信号依赖于消息队列,因此它们在一些(发射器线程未知)的时间点被异步调用.