19

誰かがQtシグナルとスロットメカニズムの実装の基本的な考え方を説明できますか? これらすべての Q_OBJECT マクロが「プレーンな C++ で」何をするのか知りたいです。この質問は、シグナルとスロットの使用に関するものではありません。

追加: Qt は moc コンパイラを使用して Qt-C++ をプレーンな C++ に変換することを知っています。しかし、モックは何をしますか?「moc_filename.cpp」ファイルを読み込もうとしましたが、このようなものが何を意味するのかわかりません

void *Widget::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_Widget))
    return static_cast<void*>(const_cast< Widget*>(this));
return QDialog::qt_metacast(_clname);
}
4

3 に答える 3

22

Concerning the signals and slots, the Q_OBJECT macro adds a virtual function qt_metacall() declaration into the class’s declaration which is to be defined later by the the moc. (It also adds some declarations for conversion but that’s not too important here.)

The moc then reads the header file and when it sees the macro, it generates another .cpp file named moc_headerfilename.cpp with the definitions to the virtual functions and – you might have asked yourself why you can get away with mentioning the signals: in your header file without a proper definition – of the signals.

So, when a signal is called, the definition from the mocfile is executed and QMetaObject::activate() is called with the signal’s name and the signal’s arguments. The activate() function then figures out which connections have been established and fetches the names for the appropriate slots.

Then it calls qt_metacall with the slot names and the arguments given to the signal and the metacall function delegates this with the help of a large switch—<code>case statement to the real slots.

As there is no real runtime information possible in C++ concerning the actual names for the signals and slots, as has already been noticed, these will be encoded by the SIGNAL and SLOT macros to simple const char*s (with either "1" or "2" added to the name to distinguish signals from slots).

As is defined in qobjectdefs.h:

#define SLOT(a)     "1"#a
#define SIGNAL(a)   "2"#a

—</p>

The other thing the Q_OBJECT macro does is defining the tr() functions inside your object which can be used to translate your application.

Edit As you asked what the qt_metacast is doing. It checks whether an object belongs to certain class and if it does returns the pointer to it. If it doesn’t, it returns 0.

Widget* w = new Widget();
Q_ASSERT(w->qt_metacast("Widget") != 0);
Q_ASSERT(w->qt_metacast("QWidget") != 0);
Q_ASSERT(w->qt_metacast("QObject") != 0);
Q_ASSERT(w->qt_metacast("UnrelatedClass") == 0);

This is needed to provide some runtime reflection which is not possible otherwise. The function is called in QObject::inherits(const char *) for example and simply checks for inheritance.

于 2010-01-05T19:30:10.333 に答える
-1

基本的な考え方は、オブジェクトを接続して、シグナルが完了したときにメソッド (スロット) を実行できるようにすることです。

connect(pistol,SIGNAL(sigShoot()),runner,SLOT(slotRun()))

上記の接続を行うと、ピストルが信号を発すると、ランナーはそのスロットを実行します。

これを行うには、それぞれのクラスでシグナルとスロットを宣言する必要があります。

が基本的な考え方です。

幸運を!

于 2010-01-05T19:10:45.323 に答える