Pure virtual class with singals and slots
-
Hello.
I want to write a small tool and like to separate the business logic from the GUI so I can easily make and use different GUIs.
Therefore I've made a class which contains the business logic called AppCore. The GUI class(es) are called MainWindow.
My idea is to pass the constructor of the AppCore a reference to the GUI so the constructor of the AppCore can connect the AppCore singals to the GUI slots and vice versa.
But to make it flexible I don't want to have the actual GUI as type of the parameter but an Interface (pure virtual class) called IGui which the GUI inherits from.
@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
AppCore *appCore;
MainWindow w;appCore = new AppCore(&w);
w.show();return a.exec();
}class IGui
{
public slots:
virtual void slot() = 0;signals: virtual void signal() = 0;
};
class MainWindow : public QMainWindow, public IGui
{
Q_OBJECTpublic: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void slot(); signals: void signal(); private: Ui::MainWindow *ui;
};
class AppCore : public QObject
{
Q_OBJECTpublic: explicit AppCore(IGui *gui, QObject *parent = 0); signals: void doSlot(); private slots: void onSingal(); ... ...
}
AppCore::AppCore(IGui *gui, QObject *parent) :
QObject(parent)
{
connect(gui, SIGNAL(signal()),
this, SLOT(onSingal()));connect(this, SIGNAL(doSlot()), gui, SLOT(slot()));
}@
But when I try to compile I get errors:
[quote]
AppCore.cpp: In constructor 'AppCore::AppCore(IGui*, QObject*)':
AppCore.cpp:9: error: no matching function for call to 'AppCore::connect(IGui*&, const char [10], AppCore* const, const char [12])'
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:204: note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:217: note: static bool QObject::connect(const QObject*, const QMetaMethod&, const QObject*, const QMetaMethod&, Qt::ConnectionType)
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:337: note: bool QObject::connect(const QObject*, const char*, const char*, Qt::ConnectionType) const
AppCore.cpp:12: error: no matching function for call to 'AppCore::connect(AppCore* const, const char [10], IGui*&, const char [8])'
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:204: note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:217: note: static bool QObject::connect(const QObject*, const QMetaMethod&, const QObject*, const QMetaMethod&, Qt::ConnectionType)
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:337: note: bool QObject::connect(const QObject*, const char*, const char*, Qt::ConnectionType) const[/quote]If I let IGui derive from QObject I get this errors:
[quote]
release\moc_MainWindow.cpp: In static member function 'static void MainWindow::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)':
release\moc_MainWindow.cpp:52: error: 'QObject' is an ambiguous base of 'MainWindow'
release\moc_MainWindow.cpp: In member function 'virtual const QMetaObject* MainWindow::metaObject() const':
release\moc_MainWindow.cpp:78: error: 'QObject' is an ambiguous base of 'MainWindow'
release\moc_MainWindow.cpp:78: error: 'QObject' is an ambiguous base of 'MainWindow'
release\moc_MainWindow.cpp: In member function 'virtual int MainWindow::qt_metacall(QMetaObject::Call, int, void**)':
release\moc_MainWindow.cpp:98: error: 'QObject' is an ambiguous base of 'MainWindow'
release\moc_MainWindow.cpp: In member function 'virtual void MainWindow::signal()':
release\moc_MainWindow.cpp:107: error: 'QObject' is an ambiguous base of 'MainWindow'
[/quote]How do I have to do it right?
-
Either don't base on QObject, but use Q_SLOTS and Q_SIGNALS macros (I'm not sure if that would work, though), or make IGui into a QMainWindow, and inherit from it.
-
I should explain a bit more:
You are getting errors about connect because MOC needs the Q_OBJECT macros to properly preprocess headers.
You get "... is an ambiguous base of MainWindow", because both classes you try to inherit from, are children of QObject, and compiler is confused. -
I remember something about not being allowed to derive from QObject in a pure virtual Class when combined with multiple inheritance. I had a problem with a class like that, that worked using QT 4.7.something (no complier warning or error) and when updating to 4.8.something the complier (or moc) reported an error.
Edit: here are some links related to the problem I experienced.
-
"link1":http://stackoverflow.com/questions/5403810/qt-multiple-inheritance-and-signals
-
"link3":http://qt-project.org/doc/qt-4.8/moc.html#multiple-inheritance-requires-qobject-to-be-first ("Virtual inheritance with QObject is not supported.")
-
-
If I've understood it right the answer of Dave Mateer in link1 would solve my problem?!?
But I don't understand completely how to do it, or I'm doing it wrong. This is my modified code:
@
class IGui
{
protected:
virtual void slot() = 0;
virtual void signal() = 0;
};class MainWindow : public QMainWindow, public IGui
{
Q_OBJECTpublic:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();private slots:
virtual void slot();signals:
virtual void signal();private:
Ui::MainWindow *ui;
};
@The rest of the code remains the same. But I still get compile errors for the connect functions
[quote]
AppCore.cpp: In constructor 'AppCore::AppCore(IGui*, QObject*)':
AppCore.cpp:9: error: no matching function for call to 'AppCore::connect(IGui*&, const char [10], AppCore* const, const char [12])'
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:204: note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:217: note: static bool QObject::connect(const QObject*, const QMetaMethod&, const QObject*, const QMetaMethod&, Qt::ConnectionType)
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:337: note: bool QObject::connect(const QObject*, const char*, const char*, Qt::ConnectionType) const
AppCore.cpp:12: error: no matching function for call to 'AppCore::connect(AppCore* const, const char [10], IGui*&, const char [8])'
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:204: note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:217: note: static bool QObject::connect(const QObject*, const QMetaMethod&, const QObject*, const QMetaMethod&, Qt::ConnectionType)
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:337: note: bool QObject::connect(const QObject*, const char*, const char*, Qt::ConnectionType) const
[/quote] -
The answer is in the compiler error:
[quote author="rubikon" date="1346742624"]
AppCore.cpp: In constructor 'AppCore::AppCore(IGui*, QObject*)':
AppCore.cpp:9: error: no matching function for call to 'AppCore::connect(IGui*&, const char [10], AppCore* const, const char [12])'
c:\QtSDK\Desktop\Qt\4.8.1\mingw\include\QtCore/qobject.h:204: note: candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)
[/quote]
the connect statement needs a const QObject pointer as first argument, but you are handing over a IGui*&. And since IGui no longer inherits QObject this is not valid.I guess the IGui object pointed to by the pointer handed over in the AppCore constructor is really a pointer to an object of a class that is derived from your IGui interface class (e.g. your MainWindow class) so i would suggest you cast to this class in the connect statement.
something like this:
@
if(dynamic_cast<MainWindow*>(gui))
{
connect(dynamic_cast<MainWindow*>(gui), SIGNAL(signal()), this, SLOT(onSignal()));
}
@