2010-09-08 7 views
14

Alors que la révision du code Qt C++ je suis tombé sur ceci:Signal Qt virtuel?

class Foo 
{ 
    Q_OBJECT 

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

Maintenant, les signaux Qt ne peut pas avoir un corps, donc je suis surpris ce même compilable (peut-être parce que le corps est effectivement vide). Je ne vois pas non plus l'intérêt de faire un signal virtuel car ... il ne peut pas avoir de corps alors comment peut-il être outrepassé?

me manque ici quelque chose que je ou est-ce une odeur de code valide?

Répondre

15

Cela semble malodorant pour moi.

Il est valable de déclarer un signal dans une classe de base, puis l'émettre à partir d'une classe dérivée, par exemple

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

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

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

Peut-être que ce qui était censé obtenir la déclaration dans la question.

4

strictement parlant C++, il est normal qu'il compile, étant donné signal est une macro pour protected et Q_UNUSED est un casting à void. Mais vous devriez obtenir une erreur lors de l'exécution moc qui crée précisément la mise en œuvre des méthodes déclarées en tant que signaux.

+2

Il peut compiler, mais c'est toujours une violation ODR: la fonction a deux corps, un dans l'en-tête et un dans le cpp émis par le moc. – ybungalobill

2

TL; DR: Je ne sais pas ce que le code était censé faire, mais c'est faux (pas simplement sentir mauvais, c'est prima facie invalide). implémentations de signaux sont toujours destinés à être générés par moc. Le corps du signal devrait être retiré.

  1. Pour que le code fonctionne, il doit faire les trois: compiler, passer moc et link. Il est vrai que votre code compile - le compilateur C++ n'a aucune raison de ne pas le faire. Mais il ne passera pas par moc et ne le liera pas.

  2. Bien que peut-être moc n'a pas détecté certains de revenir en 2010, voici comment moc actes aujourd'hui:

    a) moc ne permet pas de définitions de signal dans les instances de la classe, la diagnostic Error: Not a signal declaration. Donc class X { Q_SIGNAL void s() {} }; le déclenche, mais pas class X { Q_SIGNAL void s(); }; void X::s() {}.

    b) moc ne permet pas une macro Q_OBJECT dans une classe ne provenant pas de QObject, avec le Error: Class contains Q_OBJECT macro but does not inherit from QObject diagnostic.

  3. Comme il ne fait aucun sens de parler de signaux dans les classes qui ne dérivent pas de QObject, supposons que le code vraiment regardé comme suit:

    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); 
    } 
    

    Cela se passé moc et compilera, mais il ne sera pas lié. L'éditeur de liens émettra un diagnostic pour la déclaration multiple de Foo::someSignal. Il y a une définition dans ce fichier, et une autre dans la source générée par moc.

Questions connexes