Подтвердить что ты не робот

Как Qt реализует сигналы и слоты?

Может ли кто-нибудь объяснить мне основную идею механизма Qt-сигналов и механизма выполнения слотов? РЕАЛИЗАЦИЯ? Я хочу знать, что делают все эти макросы Q_OBJECT "на простом С++". Этот вопрос НЕ ОБОЛОЧЕН. Использование сигналов и ампер-каналов.

добавлено: Я знаю, что Qt использует moc-компилятор для преобразования Qt-С++ в простой С++. Но что делает 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);
}
4b9b3361

Ответ 1

Что касается сигналов и слотов, макрос Q_OBJECT добавляет декларацию виртуальной функции qt_metacall() в объявление классов, которое должно быть определено позже moc. (Он также добавляет некоторые декларации для преобразования, но это не слишком важно здесь.)

Затем moc считывает файл заголовка, и когда он видит макрос, он генерирует другой файл .cpp с именем moc_headerfilename.cpp с определениями для виртуальных функций и, возможно, вы спросили себя, почему вы можете уйти с упомянув signals: в вашем файле заголовка без правильного определения - сигналов.

Итак, когда вызывается сигнал, выполняется определение из файла moc и вызывается QMetaObject::activate() с именем сигналов и аргументами сигналов. Затем функция activate() определяет, какие соединения были установлены и выбраны имена соответствующих слотов.

Затем он вызывает qt_metacall с именами слотов, а аргументы, передаваемые сигналу, и функция metacall делегирует это с помощью большого выражения switch - case в настоящие слоты.

Поскольку в С++ нет реальной информации о времени выполнения, касающейся фактических имен сигналов и слотов, как уже было отмечено, они будут закодированы макросами SIGNAL и SLOT до простого const char* (с либо "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 *) и просто проверяет наследование.

Ответ 2

Эти макросы ничего не делают "на простом С++", - они расширяются до пустых строк (я думаю).

QT использует метаобъектный компилятор, который генерирует код С++ для классов с поддержкой Q_OBJECT (реализуя, среди прочего, определяющие сигналы/слоты).

Подробнее об этом можно узнать в официальной документации .

Ответ 3

Основная идея заключается в том, что вы можете подключать свои объекты, позволяя им выполнять метод (слот), когда сигнал сделан.

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

Выполняя соединение выше, когда пистолет излучает сигнал, бегун выполнит свой слот.

Для этого вам необходимо объявить свои сигналы и слоты в соответствующих классах.

Является основной идеей.

Удачи!