2011-10-26 4 views
3

У меня есть простой класс, который останавливает и запускает таймер, когда моя программа получает и теряет фокус, но при этом дает ошибку. QObject - это неоднозначная база MyApp для каждого соединения с сигнальным слотом. Вот соответствующий код:Наследование QObject Неоднозначное основание

class MyApp : public QApplication, public QObject 
{ 
    Q_OBJECT 
    ... 
} 

Вот мой (грязный) main.cpp:

#include <QtGui/QApplication> 
    #include "qmlapplicationviewer.h" 
    #include <QObject> 
    #include <QGraphicsObject> 
    #include <QTimer> 
    #include <QVariant> 
    #include "timecontrol.h" 
    #include "scorecontrol.h" 
    #include "Retry.h" 
    #include <QEvent> 
    #include "myapp.h" 

    int main(int argc, char *argv[]) 
    { 
     MyApp app(argc, argv); 

     QmlApplicationViewer viewer; 
     viewer.setOrientation(QmlApplicationViewer::ScreenOrientationLockLandscape); 
     viewer.setMainQmlFile(QLatin1String("qml/Raker/main.qml")); 
     viewer.showExpanded(); 

     QObject *rootObject = viewer.rootObject(); 

     QTimer *timmer = new QTimer; 
     timmer->setInterval(1000); 

     TimeControl *timcon = new TimeControl; 

     scorecontrol *scorer = new scorecontrol; 

     Retry *probeer = new Retry; 

     QObject::connect(timmer, SIGNAL(timeout()), timcon, SLOT(updateTime())); 
     QObject::connect(timcon, SIGNAL(setTime(QVariant)), rootObject, SLOT(setTime(QVariant))); 
     QObject::connect(rootObject, SIGNAL(blockClicked(int, int)), scorer, SLOT(checkRight(int, int))); 
     QObject::connect(scorer, SIGNAL(setScore(QVariant)), rootObject, SLOT(setScore(QVariant))); 
     QObject::connect(scorer, SIGNAL(setState(QVariant)), rootObject, SLOT(setState(QVariant))); 

     QObject::connect(rootObject, SIGNAL(start()), probeer, SLOT(Reetry())); 
     QObject::connect(probeer, SIGNAL(start()), timmer, SLOT(start())); 
     QObject::connect(probeer, SIGNAL(stop()), timmer, SLOT(stop())); 
     QObject::connect(probeer, SIGNAL(start(int)), scorer, SLOT(randomNum(int))); 
     QObject::connect(probeer, SIGNAL(sReset()), timcon, SLOT(reset())); 
     QObject::connect(probeer, SIGNAL(tReset()), scorer, SLOT(reset())); 
     QObject::connect(timcon, SIGNAL(timeOut()), scorer, SLOT(reset())); 

     QObject::connect(timcon, SIGNAL(setState(QVariant)), rootObject, SLOT(setState(QVariant))); 
     QObject::connect(timcon, SIGNAL(changeFinal()), scorer, SLOT(changeFinal())); 
     QObject::connect(scorer, SIGNAL(setFinal(QVariant)), rootObject, SLOT(setFinal(QVariant))); 

     QObject::connect(&app, SIGNAL(focusL()), probeer, SLOT(focusL())); 
     QObject::connect(&app, SIGNAL(focusG()), probeer, SLOT(focusG())); 

     return app.exec(); 
    } 

MyApp.cpp:

#include "myapp.h" 
    #include <QDebug> 
    #include <QObject> 

    MyApp::MyApp(int argc, char **argv): QApplication(argc, argv) 
    { 
     installEventFilter(this); 
    } 

    bool MyApp::eventFilter(QObject *object, QEvent *event) 
    { 
     if (event->type() == QEvent::ApplicationDeactivate) 
     { 
      qDebug() << "Focus lost"; 
      focusL(); 
     } 
     if (event->type() == QEvent::ApplicationActivate) 
     { 
      qDebug() << "Focus gained"; 
      focusG(); 
     } 

     return false; 
    } 

ответ

9

С вашим текущим примером вы создали схему разделения наследования, где ваш объект заканчивается двойными экземплярами QObject ... существует одна база QObject для QApplication, а другая для фактического класса MyApp. Это создаст неоднозначность, поскольку доступ к унаследованному методу QObject или к элементу данных не будет точно знать, какой унаследованный базовый объект получить.

Прямо сейчас, ваша диаграмма наследования выглядит следующим образом (обратите внимание на два экземпляр QObject вашего MyApp объекта наследуемые):

| QObject |   | QObject | 
     \    /
     \   | QApplication | 
     \   /
      \   /
     | MyApp | 

Вы должны держать вашу схему наследования линейного, а не иметь схему наследования раздвоения, и это означает, что имеет производный класс, который содержит только один экземпляр базового класса. Так что вы хотите что-то вроде этого:

QObject 
     | 
     | 
    QApplication 
     | 
     | 
    MyApp 
+0

Хорошо, но теперь получите неопределенную ссылку на «vtable для MyApp» на «{» над макросом Q_OBJECT и в MyApp.cpp на обоих вхождениях MyApp в этой строке : «MyApp :: MyApp (int argc, char ** argv): QApplication (argc, argv)» – Gerharddc

+1

Как выглядит ваш 'main()'? ... Я также добавлю комментарий от Laurent о запуске 'qmake' также в вашем проекте. – Jason

+0

Я добавил свой главный вопрос в мой qeustion – Gerharddc

4

QApplication уже QObject, так что вы следует просто написать:

class MyApp : public QApplication 
{ 
    Q_OBJECT 
... 

} 
+0

Ok, но теперь получить неопределенную ссылку на «виртуальные таблицы для MyApp» на «{» выше Q_OBJECT макро, и в MyApp.cpp на обоих вхождений MyApp на этой линии : «MyApp :: MyApp (int argc, char ** argv): QApplication (argc, argv)» – Gerharddc

+2

Вы запустили qmake в своем проекте в первую очередь? –

+0

Я использую Qt Creator и, похоже, делает это автоматически – Gerharddc