Кто-то может объяснить мне основную идею о QT signals&slots РЕАЛИЗАЦИЯ механизма? Я хочу знать то, что все они макросы Q_OBJECT делают "в плоскости C++". Этот вопрос не о signals&slots использовании.
добавленный: Я знаю, что QT использует компилятор MOC для преобразования Спокойного C++ в плоскость C++. Но что делает MOC? Я пытался считать "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);
}
]Что касается сигналов и слотов, в макросе []Q_OBJECT[
] добавлена виртуальная функция []qt_metacall()[
] в декларацию класса, которая будет определена позднее с помощью []moc[
]. (Он также добавляет некоторые декларации для преобразования, но это не слишком важно)[
]moc[]moc[
] затем считывает заголовочный файл, и когда он видит макрос, он генерирует другой файл [].cpp[
] с именем []moc_headerfilename. cpp[
] с определениями для виртуальных функций и - возможно, вы спросили себя, почему вам может сойти с рук упоминание сигналов []:[
] в заголовочном файле без правильного определения - сигналов.[
]Итак, при вызове сигнала выполняется определение из moc-файла и вызывается []QMetaObject::activate()[
] с именем сигнала и его аргументами.
Затем функция []activate()[
] выясняет, какие соединения были установлены и получает имена для соответствующих слотов.[
]Затем она вызывает []qt_metacall[
] с именами слотов и аргументами, переданными сигналу, и мета-функция делегирует это с помощью большого []-[
]-[]case[
] оператора case[] в реальные слоты. [
]Так как в языке С++ отсутствует реальная информация о реальном времени исполнения, касающаяся реальных имен сигналов и слотов, как уже было замечено, они будут закодированы макросами []SIGNAL[
] и []SLOT[
] в простые []const char*[
]s (с добавлением либо "1", либо "2" к имени, чтобы отличить сигналы от слотов). [
]Как определено в []qobjectdefs.h[
]:[
#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
]
[]-[
] []Другое, что делает макрос []Q_OBJECT[
], это определяет функции []tr()[
] внутри вашего объекта, которые могут быть использованы для перевода вашего приложения.[
][]Edit[]].
Как вы спросили, что делает []qt_metacast[
]. Он проверяет, принадлежит ли объект определенному классу и возвращает ли он указатель на него. Если нет, то возвращается 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);
]
[]Это необходимо для того, чтобы обеспечить некоторое отражение во время выполнения, что в противном случае невозможно. Например, функция вызывается в [][]QObject::inherits(const char *)[
][] и просто проверяет наследование.[
Эти макросы ничего не делают "в обычном C++", - они расширяются до пустых строк (я думаю).
QT использует мета-объектный компилятор, который генерирует код C++ для классов с поддержкой Q_OBJECT (реализовывает сигналы/слоты, которые вы определяете, среди прочего).
Подробнее об этом можно прочитать в официальной документации.
.Основная идея заключается в том, что Вы можете подключать свои объекты, позволяя им выполнять метод (слот), когда сигнал выполнен.
connect(pistol,SIGNAL(sigShoot()),runner,SLOT(slotRun()))
Выполняя соединение выше, когда пистолет излучает сигнал, бегунок выполнит свой слот.
Для этого необходимо объявить свои сигналы и слоты в соответствующих классах.
Это основная идея.
Удачи!