Digamos que tengo esta señal:
signals:
void progressNotification(int progress);
Recientemente aprendí sobre la palabra clave emit en Qt. Hasta ahora, solía ejecutar señales llamándolas como una función regular. Entonces en lugar de:
emit progressNotification(1000 * seconds);
Yo escribiría:
progressNotification(1000 * seconds);
Llamarlos así parecía funcionar, y todas las ranuras conectadas se ejecutarían, entonces, ¿usar la palabra clave emit causa un comportamiento diferente, o es solo azúcar sintáctico?
emit
no es necesario. Sin embargo, es extraño que haya aprendidoemit
mucho después de llamar a las señales directamente, ya que el sistema de ranura de señal es una de las primeras cosas que debe aprender sobre Qt.Respuestas:
emit
es simplemente azúcar sintáctico. Si observa la salida preprocesada de la función que emite una señal, veráemit
que acaba de desaparecer.La "magia" ocurre en el código generado para la función de emisión de señales, que puede observar inspeccionando el código C ++ generado por moc.
Por ejemplo, una
foo
señal sin parámetros genera esta función miembro:Y el código
emit foo();
está preprocesado para simplementefoo();
emit
se define enQt/qobjectdefs.h
(en el sabor de código abierto de la fuente de todos modos), así:(La protección de definición es para permitirle usar Qt con otros marcos que tienen nombres en
no_keywords
conflicto a través de la opción de configuración QMake).fuente
emit
que realmente hizo más que nada? Encuentro que tener el 'azúcar sintáctico' en este caso solo confunde al novato (o al menos a mí cuando era un usuario novato de Qt) - parece que algo mágico o importante está sucediendo con laemit
pseudo-palabra clave, cuando no hace nada en todo: toda la magia ocurre en una función antigua regular quemoc
crea (moc
es la magia para las señales Qt y las ranuras).emit
Es una decoración innecesaria que no hace más que parecer importante.emit
le dice a la persona que lee la llamada que la magia está a punto de suceder (es decir, esto activará el código en objetos de los que esta clase posiblemente nunca haya oído hablar, y estas llamadas pueden ser sincrónicas o asincrónicas), lo que esencialmente se pierde por completo si omite la palabra clave. Úselo. Se documenta automáticamente. Los "principiantes" deben leer documentos y tutoriales, yemit
siempre está ahí (de todos modos, en los documentos oficiales). Descubrir que puede simplemente llamar a la función debería suceder después de haber "visto la luz"; ya no es un novato en ese momento.emit
'palabra clave'. Creo que hubiera preferido que se usara una convención de nomenclatura si fuera necesario dejar en claro que una llamada a función es una señal.emit
.emit
comentario de palabra clave pseudo era dejar en claro que se está invocando una señal, entonces una convención de nomenclatura podría hacer lo mismo, sin misterio y con beneficios similares. Qt no pudo hacer cumplir la convención de nomenclatura (en realidad,moc
podría hacerla cumplir, pero tampoco estoy defendiendo eso), pero Qt no puede hacer cumplir el uso deemit
ninguno de los dos. Y aunque puede 'apagar'emit
si hay un conflicto de nombres, eso no ayuda mucho si tiene un montón de archivos fuente que lo están usando (innecesariamente, para arrancar).Después de 18 meses ... comencé con comentarios en la respuesta de @ Mat, y me estaba quedando sin espacio rápidamente. De ahí la respuesta.
IMO
emit
no es azúcar sintáctico ni una palabra clave simple en el sentido de queconnect
mecanismo a reconocer que de hecho es unsignal
, yTodo el sistema de señal / ranura es un idioma diferente al de una simple llamada de función. Creo que se deriva del patrón del observador. También hay una gran diferencia entre ay
signal
aslot
: no es necesario implementar una señal , ¡mientras que una ranura debe serlo !Estás caminando por la calle y ves una casa en llamas (una señal). Usted marca el 911 ( conecte la señal de incendio con la ranura de respuesta del 911 ). La señal solo fue emitida , mientras que la ranura fue implementada por el departamento de bomberos. Puede ser impreciso, pero entiendes la idea. Veamos el ejemplo de OP.
Algún objeto de backend sabe cuánto se ha avanzado. Entonces podría simplemente
emit progressNotification(...)
señalar. Depende de la clase que muestra la barra de progreso real, recoger esta señal y ejecutarla. Pero, ¿cómo se conecta la vista a esta señal? Bienvenido al sistema de señal / ranura de Qt. Ahora se puede concebir una clase de administrador (normalmente una especie de widget), que consta de un objeto de vista y un objeto de cálculo de datos (ambos sonQObjects
), que puede realizarconnect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress)
.No entremos en los aspectos de diseño de la clase de administrador, pero basta con decir que aquí es donde brilla el sistema de señal / ranura. Puedo concentrarme en diseñar una arquitectura muy limpia para mi aplicación. No siempre, pero muchas veces, encuentro que simplemente emito señales pero implemento ranuras .
Si es posible usar / llamar a un método de señal sin siquiera emitirlo , entonces necesariamente implica que nunca necesitó esa función como señal en primer lugar.
fuente
emit
hecho es solo una macro vacía y puramente opcional. No así las palabras clavesignal
yslot
que son procesadas por el moc.signal
se usa para proporcionar la implementación de la función,slot
se usa para crear la entrada del meta objeto para que se encuentre con laSLOT(MySlot())
macro o en QML.emit
es suggar sintáctico. Nada se quejará nunca si escribeemit i++;
(pero tal vez sus compañeros de trabajo) y aún no puede conectarsei++
.La segunda opción implicaría que siempre sabrá cuál es el nombre de la función y los parámetros de la función y que el objeto al que lo está enviando es conocido por esa función en particular. Esos dos casos no siempre son ciertos, por lo que son las dos cosas principales por las que se han creado ranuras y señales. "debajo del capó", el mecanismo de señal y ranura es solo una tabla con indicadores para cada función que está conectada.
Además, mire este pdf que explica muy claramente la naturaleza de las señales y el mecanismo de ranuras: http://www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf
fuente
emit
era solo una operación no válida. Pero incluso en este caso, la lectura del cuerpo de la pregunta debería haber aclarado las cosas, así que -1.