14

呼び出すことは有効ですか

QObject::connect(a, SIGNAL(somesig(someparam)), b, SLOT(someslot()));

パラメータなし?動作しているように見えますが (実行時例外はスローされません)、ドキュメントに参照が見つかりません。私が見つけたのは、 someslot にデフォルトのパラメーターがある場合にこれが可能であるということだけです。この場合有効です。しかし、私のメソッド someslot には、デフォルトと同じパラメーターセットがありません (この例ではパラメーターはありません)。

では、より少ないパラメータでスロットに信号を配線することは可能でしょうか?

4

2 に答える 2

22

はい、大丈夫です。Signals & Slotsのドキュメントに短い文があります。

[...] 信号の署名は、受信スロットの署名と一致する必要があります。(実際、スロットは、余分な引数を無視できるため、受信したシグナルよりも短いシグネチャを持つ場合があります。 ) [...]

デフォルトの引数が説明されているページのさらに下に、そのような例さえあります。

于 2013-08-22T18:53:38.273 に答える
3

標準 C++ に関しては、Qt ソリューションも同様に機能します。

シグナルの送信は、メソッドを呼び出すことによって行われます。

emit someSignal(3.14);

emitキーワードは実際には空の に解決されるため、上記の行は指定された引数で#defineメソッドを呼び出すだけです。メソッドは、次のように派生クラスsomeSignal内で宣言されている可能性があります。QObject

class SomeObject: public QObject {
    Q_OBJECT
public slots:
    void firstSlot() { /* implementation */ }
    void secondSlot(double) {  /* implementation */ }

signals:
    void someSignal(double);  /* no implementation here */
};

これはよく知られているように思われるかもしれませんが、シグナルの実際の実装がどこから来るのか疑問に思っているかもしれません。お察しのとおり、ここで Qt のメタ オブジェクト コンパイラ (MOC) が機能します。セクション内で宣言さsignalsれたすべてのメソッドに対して、生成されたソースで次のような実装が提供されます。

void SomeObject::someSignal(double _t1)
{
    void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
    QMetaObject::activate(this, &staticMetaObject, 1, _a);
}

興味深い部分はvoid *_a[]、シグナルに渡された引数へのポインターで満たされたベクトルです。ここでは特に何もありません。

引数 vector が に渡されQMetaObject::activate、次にスレッド セーフ チェックとその他のハウスキーピングが行われ、シグナルに接続されているスロットがあれば、そのスロットの呼び出しが開始されます。シグナルからスロットへの接続は実行時に解決されるため (connect()動作する方法)、MOC からの少しの支援が再び必要になります。特に、MOC はqt_static_metacall()クラスの実装も生成します。

void SomeObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    if (_c == QMetaObject::InvokeMetaMethod) {
        SomeObject *_t = static_cast<SomeObject *>(_o);
        Q_UNUSED(_t)
        switch (_id) {
        case 0: _t->firstSlot(); break;
        case 1: _t->secondSlot((*reinterpret_cast< double(*)>(_a[1]))); break;
        default: ;
        }
    } /* some more magic */
}

ご覧のとおり、このメソッドには、void *_a[]前のベクトルを関数呼び出しに解決するもう一方の端が含まれています。また、可変引数リスト (省略記号を使用...) やその他の疑わしいトリックが含まれていないこともわかります。

したがって、元の質問を啓発するために、たとえばが信号の署名に一致する にsomeSignal(double)接続されている場合、呼び出しは に解決され、期待どおりに引数を渡すだけです。secondSlot(double)case 1qt_static_metacall

firstSlot()シグナルより引数の少ないにシグナルを接続すると、呼び出しは に解決されcase 0firstSlot()引数なしで呼び出されます。void *_a[]シグナルに渡された引数は、そのベクトルにそのまま残ります。

于 2017-02-12T14:58:41.217 に答える