Qt "slots privados": ¿qué es esto?

82

Entiendo cómo usarlo, pero su sintaxis me molesta. ¿Qué está haciendo "Private Slots:"?

Nunca antes había visto algo entre la palabra clave privada y: en una definición de clase. ¿Hay algo de magia elegante en C ++ aquí?

Y ejemplo aquí:

 #include <QObject>

 class Counter : public QObject
 {
     Q_OBJECT

 public:
     Counter() { m_value = 0; }

     int value() const { return m_value; }

 public slots:
     void setValue(int value);

 ...
Justin
fuente
3
Esto no es C ++ estándar, esta es la construcción del marco QT. Busque señales y ranuras QT .
Alok Save
1
Cuando se compila como C ++ slotsse define como #define slots. Al compilar usando Qt MOC, genera código para el compilador de C ++.
dalle
2
jajaja, esto fue aún más difícil de entender para mí porque no he usado C ++ en tanto tiempo, pensé que agregaron algo nuevo
dtc

Respuestas:

56

Las ranuras son una extensión específica de Qt de C ++. Solo se compila después de enviar el código a través del preprocesador de Qt, el compilador de metaobjetos (moc). Consulte http://doc.qt.io/qt-5/moc.html para obtener documentación.

Editar: como señala Frank, solo se requiere moc para vincular. Las palabras clave adicionales se #definen con el preprocesador estándar.

Russell Davis
fuente
Gracias, el preprocesador de Qt es lo que me faltaba en mi modelo mental de lo que estaba pasando.
Justin
16
No es correcto, el código se compila todo el tiempo como "señales" y "ranuras" definidas vacías, por lo que el compilador nunca las ve. Estas macros son sugerencias para moc, que genera código adicional . Los archivos .hy .cpp originales no se alteran y se compilan bien sin moc. Lo que fallaría es la vinculación, ya que las definiciones generadas por moc (definiciones de señales, metaobjetos, etc.) faltan.
Frank Osterfeld
1
¿Es slotsnecesaria la palabra clave? Intenté compilar / vincular algunos pequeños programas Qt que llaman a las ranuras sin la slotspalabra clave y se han construido muy bien. Mis experimentos muestran que: signals:es definitivamente necesario, slotspodría ser innecesario y emitparece ser innecesario como he leído en otra parte.
It's Your App LLC
1
slotsno es necesario en Qt5. Qt actualizó la connect()sintaxis para permitir conectar una señal a una función arbitraria, incluidas lambdas. Por eso, slotsno es necesario. Sin embargo, la slotspalabra clave aún afecta la forma en que QMetaObjectse construye un objeto . moc(también conocido como el "compilador de metaobjetos") no reconocerá un método como una ranura a menos que esté dentro de la slots:sección de una definición de clase. Entonces, aunque la conexión seguirá funcionando, el método no se mostrará en las herramientas de introspección.
Chris
19

Las palabras clave como public, privatese ignoran para las ranuras Qt. Todas las ranuras son públicas y se pueden conectar

Andrés
fuente
30
Cuando se llama al método a través de un mecanismo de señal / ranura, los especificadores de acceso se ignoran. Pero las tragamonedas también son métodos "normales". Cuando los llama de la forma tradicional, se consideran los especificadores de acceso.
borges
4
@borges y los futuros lectores. En Qt5, el método connect () puede usar punteros de función (lo cual tiene ventajas). Si se conecta con punteros de función, los especificadores de acceso se aplican en el mecanismo de señales / ranuras.
Tod
3
@borges Creo que esto es incorrecto, o al menos la explicación no estaba clara. Los especificadores de acceso no restringen su capacidad para conectar señales a las ranuras; es decir, se puede conectar una ranura privada a cualquier señal. Sin embargo, el especificador de acceso protege la función miembro de su clase (de la manera típica) mientras se invoca. Por lo tanto, los especificadores de acceso no se "ignoran" cuando se llaman a través del mecanismo de señal / ranura: no tienen nada que ver con la conexión de ranuras a señales, pero protegen la función de thisla forma en que estamos familiarizados.
It's Your App LLC
4

Declarar las tragamonedas como privadas significa que no podrá hacer referencia a ellas desde el contexto en el que son privadas, como cualquier otro método. En consecuencia, no podrá transferir direcciones de ranuras privadas connect.

Si declara la señal como privada, está diciendo que solo esta clase puede administrarla, pero los punteros de miembros de función no tienen restricciones de acceso :

class A{
    private:
    void e(){

    }
    public:
    auto getPointer(){
        return &A::e;   
    }
};

int main()
{
    A a;
    auto P=a.getPointer();
    (a.*P)();
}

Aparte de eso, lo que mencionan otras respuestas también es válido:
- todavía puede conectar señales privadas y ranuras desde el exterior con trucos
- signalsy slotsson macros vacías y no rompen el estándar del lenguaje

Euri Pinhollow
fuente
¿Por qué esta pregunta no tiene ningún voto positivo? ¿Hay algo malo con eso? Encuentro slotsútil la declaración, que es una macro. No puedo conectar punteros de función de ranura privados connectsin trucos, ¿verdad?
Arch Linux Tux