Вопрос по c++ – Использование emit против вызова сигнала, как будто это обычная функция в Qt

86

Допустим, у меня есть этот сигнал:

signals:
    void progressNotification(int progress);

Я только недавно узнал о ключевом слове emit в Qt. До сих пор я выполнял сигналы, просто вызывая их как обычную функцию. Так что вместо:

emit progressNotification(1000 * seconds);

Я бы написал:

progressNotification(1000 * seconds);

Кажется, что их вызов такой, что все работает, и все подключенные слоты будут работать, вызывает ли использование ключевое слово emit другое поведение, или это просто синтаксический сахар?

+ 1 никогда не зналemit не нужен. Странно, что вы узнали оemit через некоторое время после непосредственного вызова сигналов, так как система слотов сигналов - это одна из первых вещей, которую нужно узнать о Qt. Christian Rau

Ваш Ответ

3   ответа
80

emit - это просто синтаксический сахар. Если вы посмотрите на предварительно обработанный вывод функции, которая излучает сигнал, вы увидитеemit только что ушел.

«Волшебство» происходит в сгенерированном коде для функции передачи сигнала, которую вы можете посмотреть, изучив код C ++, сгенерированный moc.

Например,fooигнал @ без параметров генерирует эту функцию-член:

void W::foo()
{
    QMetaObject::activate(this, &staticMetaObject, 0, 0);
}

И кодemit foo(); предварительно обрабатывается до простогоfoo();

emit определяется вQt/qobjectdefs.h (во всяком случае, с открытым исходным кодом), например:

#ifndef QT_NO_EMIT
# define emit
#endif

(Определить охрану - это позволить вам использовать Qt с другими фреймворками, имена которых совпадают черезno_keywords QMake config option.)

Хмм, я не уверен, что согласен с тобой, насколько ценemit "ключевое слово" есть. Я думаю, что предпочел бы использовать соглашение об именах, если есть необходимость прояснить, что вызов функции является сигналом. Michael Burr
Знаете ли вы, была ли когда-либо реализация (или запланированная реализация)emit что на самом деле больше чем ничего? Я обнаружил, что наличие «синтаксического сахара» в этом случае просто смущает новичка (или, по крайней мере, меня, когда я был новичком в Qt) - кажется, что с @ происходит что-то волшебное или важноemit псевдо-ключевое слово, когда оно вообще ничего не делает - вся магия происходит в обычной старой функции, котораяmoc создает moc это магия для сигналов Qt и слотов).emit - ненужное украшение, которое только и делает, что кажется важным. Michael Burr
Emit isн "просто украшение".emit говорит человеку, читающему вызов, о том, что волшебство вот-вот должно произойти (то есть это вызовет код в объектах, о которых этот класс потенциально никогда не слышал, и эти вызовы могут быть синхронными или асинхронными), что по существу полностью теряется, если вы опустите ключевое слово , Используй это. Это автоматическое документирование. «Новички» должны читать документы и учебники, а такжеemit всегда есть (в любом случае, в официальных документах). Обнаружение того, что вы можете просто вызвать функцию, должно произойти после того, как вы «увидели свет» - в этот момент вы больше не новичок. Mat
Ну, я в корне не согласен с этим :) Принудительное соглашение об именах - это то, что вы можете сделать сами в своих проектах / на рабочем месте, Qt не препятствует этому. Qt не заставляет вас использовать «ключевое слово», и даже позволяет отключить его, если оно конфликтует с другими частями вашего кода. На мой взгляд, подход с использованием ключевых слов лучше - компилятор не может помочь вам обеспечить соблюдение политики именования, но он поймает неправильно написанноеemit. Mat
Чтобы быть ясным - я не защищал использование соглашения об именах - только этоесл причинаemit psuedo-keyword-comment должен был прояснить, что сигнал вызывается, тогда соглашение об именовании может сделать то же самое, без каких-либо загадок и с аналогичными преимуществами. Соглашение об именах не может быть применено Qt (на самом деле,moc может обеспечить это - но я тоже не защищаю это), но Qt не может принудительно использоватьemit или. И пока вы можете «выключить»emit если есть конфликт имен, это мало поможет, если у вас есть несколько исходных файлов, которые его используют (без необходимости, для загрузки). Michael Burr
2

и мне быстро не хватало места. Таким образом, ответ.

IMOemit не является ни синтаксическим сахаром, ни простым ключевым словом в том смысле, что

Он генерирует код (как описано выше в @Mat), Это помогаетconnect механизм признает, что это действительноsignal, а такж Это делает ваш сигнал частью «более крупной» системы, где сигналы и ответы (слоты) могут выполняться синхронно или асинхронно или помещаться в очередь, в зависимости от того, где и как был получен сигнал. Это чрезвычайно полезная функция системы сигналов / слотов.

Вся система сигнал / слот отличается от простого вызова функции. Я полагаю, что это происходит из схемы наблюдателя. Существует также большая разница междуsignal иslot: сигналне имее будет реализовано, а слотдолжно быт!

Вы идете по улице и видите дом в огне (сигнал). Вы набираете 911 Подключите пожарный сигнал к 911 слоту ответ). Сигнал был только излучаемый, тогда как слот был реализован у пожарной части. Может быть неточным, но вы поняли идею. Давайте посмотрим на пример OP.

Какой-то бэкэнд-объект знает, как много было сделано. Так что это может простоemit progressNotification(...) сигнал. Это зависит от класса, который отображает фактический индикатор выполнения, чтобы поднять этот сигнал и выполнить его. Но как вид соединяется с этим сигналом? Добро пожаловать в систему сигналов / слотов Qt. Теперь можно представить класс менеджера (обычно это своего рода виджет), который состоит из объекта представления и объекта вычисления данных (оба являютсяQObjects), может выполнятьconnect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress).

Давайте не будем вдаваться в аспекты дизайна класса менеджера, но достаточно сказать, что именно здесь работает система сигнал / слот. Я могу сосредоточиться на разработке очень чистой архитектуры для моего приложения. Не всегда, но часто я нахожу, что я излучайте сигналы только при наличии слотов.

Если есть возможность использовать / вызвать метод сигнала никогда не излучая его, то это обязательно означает, что ты никогда не нуждался в этой функции в качестве сигнала в первую очередь

Нет,emit действительно является пустым макросом и является необязательным. Не так ключевые словаsignal а такжеslot которые обрабатываются МОК.signal используется для обеспечения реализации функции,slot используется для создания метаобъекта, поэтому его можно найти с помощьюSLOT(MySlot()) макрос или в QML.emit - синтаксический сахар. Ничто не будет жаловаться, если вы напишитеemit i++; (но, возможно, ваши коллеги), а вы все еще не можете подключиться кi++. derM
-3

что вы всегда знаете, каково имя функции и параметры функции, и что объект, которому вы ее отправляете, известен именно этой функции. Эти два случая не всегда верны, так что это две основные причины, по которым были созданы слоты и сигналы. «скрытый» механизм сигналов и слотов - это просто таблица с указателями на каждую подключенную функцию.

Также посмотрите этот PDF-файл, который очень четко объясняет природу механизма сигналов и слотов:http: //www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pd

В обоих случаях необходимо знать имя сигнала и его параметры - вы излучаете его, как вы можете излучать то, чего не знаете? Оба имеют одинаковую семантику, они идентичны. Mat
Может быть, вы испортили сигнальный звонок с прямым слот-вызовом? Но я должен признать, что сначала я задавался вопросом о названии вопроса, так как никогда не зналemit был просто запретом. Но даже в этом случае чтение тела вопроса должно было прояснить ситуацию, так что -1. Christian Rau

Похожие вопросы