2009-07-22 10 views
7

Así que he empezado a aprender Qt 4.5 y he encontrado que el mecanismo de Señal/Ranura es de ayuda. Sin embargo, ahora me encuentro considerando dos tipos de arquitectura.Llamada de señal/ranura vs. función directa

este es el que yo usaría

class IDataBlock 
{ 
    public: 
    virtual void updateBlock(std::string& someData) = 0; 
} 

class Updater 
{ 

    private: 
    void updateData(IDataBlock &someblock) 
    { 
     .... 
     someblock.updateBlock(data); 
      .... 
    } 
} 

Nota: el código inline por razones de brevedad.

Ahora, con señales que pude simplemente

void Updater::updateData() 
{ 
    ... 
    emit updatedData(data); 
} 

Esto es más limpio, reduce la necesidad de una interfaz, pero debería hacerlo sólo porque pude? El primer bloque de código requiere más tipeo y más clases, pero muestra una relación. Con el segundo bloque de código, todo es más "sin forma". Cuál es más deseable, y si es una base de caso por caso, ¿cuáles son las pautas?

Respuesta

9

Emmitir una señal cuesta pocos conmutadores y algunas llamadas a funciones adicionales (dependiendo de qué y cómo esté conectado), pero la sobrecarga debe ser mínima.

El proveedor de una señal no tiene control sobre quiénes son sus clientes e incluso si todos obtuvieron la señal en el momento en que emiten devoluciones.

Esto es muy conveniente y permite el desacople completo, pero también puede causar problemas cuando el orden de ejecución importa o cuando desea devolver algo.

Nunca pase punteros a datos temporales (a menos que sepa exactamente lo que está haciendo e incluso entonces ...). Si debe, pase la dirección de su variable miembro - Qt proporciona una forma de retrasar la destrucción del objeto hasta después de todos los eventos para que se procese.

Las señales también pueden requerir que el bucle de evento se esté ejecutando (a menos que la conexión sea directa, creo).

En general, tienen mucho sentido en las aplicaciones impulsadas por eventos (en realidad, rápidamente se vuelve muy molesto sin ellas).

Si ya utiliza Qt en un proyecto, definitivamente úselos. Si la dependencia de Qt es inaceptable, boost tiene un mecanismo similar.

3

Hay otra diferencia. # 1 está acoplado a la interfaz IDataBlock, y la clase Updater necesita saber sobre "someblock". # 2 puede acoplarse tarde a través de una llamada de conexión (o varias, incluidas las desconexiones), lo que conduce a un enfoque más dinámico. # 2 actúa como un mensaje (piense en Smalltalk/ObjC) y no en una llamada (piense en C/C++). Los mensajes también pueden estar sujetos a despacho múltiple, lo que requiere la implementación manual de esa función en el n. ° 1.

Mi preferencia sería utilizar señales/slots debido a su flexibilidad, a menos que el rendimiento del código o la necesidad de datos de retorno inmediatos no lo permitan (o la dependencia de Qt no es deseable).

2

Las dos formas pueden parecer similares. Funcionalmente, eso es verdad. En la práctica, estás resolviendo un problema más grande. En esos casos, las circunstancias externas harán que estas dos soluciones no sean equivalentes.

Un caso común es averiguar la relación entre fuente y sumidero. ¿Se conocen el uno al otro? En su primer ejemplo, updateData() necesita que se pase el sink. Pero, ¿y si el activador es un botón GUI [Update Data]? Los botones son componentes genéricos y no deberían saber sobre IDataBlock.

Una solución es, por supuesto, agregar un miembro de m_someblock a Updater. El botón ahora actualizará cualquier miembro que esté en Updater. Pero, ¿es esto realmente lo que pretendías?

Cuestiones relacionadas