¿Las señales de Qt pueden ser públicas o privadas?

6 minutos de lectura

avatar de usuario
antón

¿Las señales de Qt pueden ser públicas o privadas? ¿Puedo crear señales internas, que solo se ven dentro de la clase?

Actualizar: Tengo una clase con algunas señales internas. ¿Cómo puedo hacer que esas señales sean invisibles para otras clases (encapsulación y ocultación de información)?

  • Use el patrón PIMPL en ese caso.

    – jue. Thielemann

    21 oct 2020 a las 20:06


avatar de usuario
Andrei Vlasuk

No. Las señales no pueden ser públicas ni privadas. Las señales Qt son métodos de clase protegidos.

La palabra clave “señales” se define en qobjectdefs.h (línea 69 como para Qt 4.6.1):

#   define signals protected

ACTUALIZAR: las señales son sólo protected hasta e incluyendo todas las versiones menores de Qt 4. Desde Qt 5.0 en adelante, son public. Consulte https://stackoverflow.com/a/19130831.

  • Creo que las señales ahora se consideran public ver aquí stackoverflow.com/questions/19129133/…

    – johnbakers

    2 de octubre de 2013 a las 5:40

  • Parece que puede haber señales privadas: doc.qt.io/qt-5/qstate.html#finished – ¿Cómo se crean?

    – derM

    27 de julio de 2017 a las 14:35

  • El cambio era necesario para hacer uso de la sintaxis de C++11 en connect funciones, donde se proporciona la devolución de llamada a la función en lugar de una señal o ranura con nombre.

    -mip

    24 de julio a las 17:19

avatar de usuario
franco osterfeld

Una forma común, por ejemplo, vista en kdelibs, es esta:

Q_SIGNALS:
#ifndef Q_MOC_RUN
    private: // don't tell moc, doxygen or kdevelop, but those signals are in fact private
#endif

   void somePrivateSignal();

Esto hace que la señal sea privada, es decir, solo puede ser emitida por la propia clase pero no por sus subclases. Para no hacer que el “privado:” anule Q_SIGNALS (moc no vería somePrivateSignal como señal entonces), está dentro de Q_MOC_RUN, que solo se define cuando se ejecuta moc.

Editar: Este enfoque no funciona para las conexiones de nuevo estilo introducidas con Qt 5 (connect(a, &A::someSignal, b, &B::someSlot)), ya que requieren que la señal sea accesible.

  • No, como “#define Q_SIGNALS protected”, el privado: no tendrá ningún efecto

    – Frank Osterfield

    9 de enero de 2013 a las 22:20

  • Drat. ¿Por qué todo en C++ requiere un hack?

    – weberc2

    24 de junio de 2013 a las 17:34

  • “Este enfoque no funciona para las conexiones de nuevo estilo introducidas con Qt 5” — depende… Si uno solo quiere permitir conectarse a la señal internamente también (donde la ranura posiblemente podría emitir otra señal pública), entonces esto es ideal — excepto que la sintaxis anterior todavía permitiría conectarse a él…

    – Aconcagua

    9 de febrero de 2018 a las 18:52


Señales fue protected en Qt4, en Qt5 son public. Int Qt5 puedes hacerlos private añadiendo QPrivateSignal como último argumento. Más sobre esto: http://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.html

  • Buen truco: el moc ignora el último elemento en la firma de la señal en caso de que el nombre sea QPrivateSignal

    – jue. Thielemann

    9 de noviembre de 2020 a las 14:56


Las tragamonedas son métodos simples que pueden ser públicos, protegidos o privados.

Como señaló Andrei, las señales son solo una redefinición de protegido, lo que significa que solo pueden ser emitidas por la clase en la que están definidas.

Si desea que una clase emita una señal de otra, debe agregarle un método público (o ranura) como este:

void emitTheSignal(...) {
  emit theSignal(...);
}

Las señales Qt son públicas en el sentido de que cualquier objeto puede conectarse a cualquier señal.

  • también son públicos en el sentido de que cualquier otra clase puede emitirlos, ya que son funciones públicas. esto puede haber cambiado con respecto a versiones anteriores de Qt. ver aquí stackoverflow.com/questions/19129133/…

    – johnbakers

    2 de octubre de 2013 a las 5:41

  • La programación orientada a objetos utiliza la encapsulación para evitar el acceso a métodos y datos internos. En caso de que las señales sean solo para fines internos, también deben ocultarse.

    – jue. Thielemann

    9 de noviembre de 2020 a las 14:51

avatar de usuario
Nicolás Holthaus

Todas las respuestas existentes son incorrectas.

Una señal se puede hacer privada agregando un QPrivateSignal escriba a su definición como el último argumento:

signals:
  
  void mySignal(QPrivateSignal);

QPrivateSignal es una estructura privada creada en cada QObject subclase por el Q_OBJECT macro, por lo que solo puede crear QPrivateSignal objetos en la clase actual.

Técnicamente, la señal aún tiene visibilidad pública, pero solo puede ser emitida por la clase que la creó.

  • también son públicos en el sentido de que cualquier otra clase puede emitirlos, ya que son funciones públicas. esto puede haber cambiado con respecto a versiones anteriores de Qt. ver aquí stackoverflow.com/questions/19129133/…

    – johnbakers

    2 de octubre de 2013 a las 5:41

  • La programación orientada a objetos utiliza la encapsulación para evitar el acceso a métodos y datos internos. En caso de que las señales sean solo para fines internos, también deben ocultarse.

    – jue. Thielemann

    9 de noviembre de 2020 a las 14:51

avatar de usuario
jue. Thielemann

Puedes usar el patrón PIMPL para eso. Sus señales privadas existen solo en la implementación privada.

  • ¿Un PIMPL, derivado de QObject, no lo haría más pesado y empeoraría el rendimiento?

    – MasterAler

    8 de noviembre de 2019 a las 12:35

  • Sí, lleva algo de tiempo. Pero considere las siguientes preguntas: ¿Cuánto tiempo cuesta llamar a una subrutina? ¿Es relevante el rendimiento de la parte del programa relacionado?

    – jue. Thielemann

    10 de noviembre de 2019 a las 17:21

  • No estoy seguro de por qué esto fue rechazado. Utilizo este enfoque con éxito, por ejemplo, para una envoltura de máquina de estado, que internamente usa una QStateMachine pero no la expone (razones arquitectónicas). Del mismo modo, no quiero exponer las señales utilizadas para hacer que la máquina de estado haga sus transiciones, ya que de lo contrario esas señales se mezclarían con las señales de la API pública, lo que disminuiría la capacidad de mantenimiento. Dado que la máquina de estado realiza transiciones solo en las interacciones del usuario, el impacto en el rendimiento es completamente irrelevante en mi caso.

    – Tim Mayer

    9 de noviembre de 2020 a las 5:53

  • Me parece bien. Esto fue rechazado por alguien que no tiene idea sobre la teoría de la complejidad computacional y que se centra en microoptimizaciones totalmente inútiles. Empeorará el rendimiento en 0.0000001 nanosegundos… mientras que el código de los ignorantes generalmente lo empeorará 10000000 veces.

    -mip

    24 de julio a las 17:06


¿Ha sido útil esta solución?