2010-09-08 14 views
14

mentre la revisione di un codice C++ Qt mi sono imbattuto in questo:Segnale Qt virtuale?

class Foo 
{ 
    Q_OBJECT 

signals: 
    virtual void someSignal(const QString& str, int n) 
    { 
    Q_UNUSED(str); 
    Q_UNUSED(n); 
    } 
    ... 
}; 

Ora, segnali Qt non possono avere un corpo così Mi sorprende questo ancora compilazione (forse perché il corpo è effettivamente vuoto). Inoltre, non vedo il punto di rendere virtuale un segnale come ... non può avere un corpo quindi come può essere ignorato?

Mi manca qualcosa qui o si tratta di un odore di codice valido?

risposta

15

Mi sembra maleodorante.

È valido dichiarare un segnale in una classe base e quindi emetterlo da una classe derivata, ad es.

class MyBase : public QObject 
{ 
    Q_OBJECT 
// ... 
signals: 
    void somethingHappened(); 
}; 

class MyDerived : public MyBase 
{ 
    Q_OBJECT 
// ... 
    void doSomething(); 
}; 

void MyDerived::doSomething() 
{ 
    // .... 
    emit somethingHappened(); 
} 

Forse questo è ciò che la dichiarazione nella domanda era destinata a raggiungere.

4

A rigor di C++ parlando è normale che compila, data signal è una macro per protected e Q_UNUSED è un cast di void. Ma si dovrebbe ottenere un errore durante l'esecuzione di moc che crea esattamente l'implementazione dei metodi dichiarati come segnali.

+2

Può compilare, ma è ancora una violazione ODR: la funzione ha due corpi, uno nell'intestazione e uno nel cpp emesso dal moc. – ybungalobill

2

TL; DR: Non so che cosa il codice era destinato a fare, ma è sbagliato (non solo ha un cattivo odore, è prima facie non valido). Le implementazioni del segnale sono sempre destinate a essere generate da moc. Il corpo del segnale dovrebbe essere rimosso.

  1. Per il codice per lavorare, deve fare tutte e tre: la compilazione, get moc passato e collegamento. È vero che il tuo codice è compilato - il compilatore C++ non ha motivo di non farlo. Ma non passerà attraverso Moc né collegherà.

  2. Anche se forse moc non ha rilevato alcune indietro nel 2010, ecco come moc atti oggi:

    a) moc non consente definizioni dei segnali negli organi di classe, con la diagnostica Error: Not a signal declaration. Quindi lo class X { Q_SIGNAL void s() {} }; lo innesca, ma non lo è il class X { Q_SIGNAL void s(); }; void X::s() {}.

    b) moc non consente una macro Q_OBJECT in una classe non derivanti da QObject, con la diagnostica Error: Class contains Q_OBJECT macro but does not inherit from QObject.

  3. Dal momento che non ha alcun senso parlare di segnali di classi che non derivano da QObject, supponiamo che il codice sembrava davvero come segue:

    class Foo : public QObject 
    { 
        Q_OBJECT 
    signals: 
        virtual void someSignal(const QString&, int); 
    }; 
    void Foo::someSignal(const QString& str, int n) 
    { 
        Q_UNUSED(str); 
        Q_UNUSED(n); 
    } 
    

    Ciò superare moc e compilerà, ma non collegherà. Il linker invierà una diagnostica per la dichiarazione multipla di Foo::someSignal. C'è una definizione in questo file e un'altra nella sorgente generata dal moc.

Problemi correlati