Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Pure virtual class with singals and slots
Forum Updated to NodeBB v4.3 + New Features

Pure virtual class with singals and slots

Scheduled Pinned Locked Moved General and Desktop
11 Posts 4 Posters 16.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    rubikon
    wrote on last edited by
    #1

    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_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
     
    private slots:
    void slot();
     
    signals:
    void signal();
     
    private:
    Ui::MainWindow *ui;
    

    };

    class AppCore : public QObject
    {
    Q_OBJECT

    public:
    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?

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      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.

      (Z(:^

      1 Reply Last reply
      0
      • sierdzioS Offline
        sierdzioS Offline
        sierdzio
        Moderators
        wrote on last edited by
        #3

        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.

        (Z(:^

        1 Reply Last reply
        0
        • G Offline
          G Offline
          giesbert
          wrote on last edited by
          #4

          usoing signals and slots without deriving from QObject does not work, as it relies on the Q_OBJECT macro and implementations from QObject which are called in the moc files.

          Nokia Certified Qt Specialist.
          Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

          1 Reply Last reply
          0
          • R Offline
            R Offline
            rubikon
            wrote on last edited by
            #5

            So how could I write an interface with signals and slots?

            1 Reply Last reply
            0
            • G Offline
              G Offline
              giesbert
              wrote on last edited by
              #6

              Only if the interface class is derived from QObject (directly or indirectly). This implies no other way to derive from QObject (which means also not from QWidget).

              Nokia Certified Qt Specialist.
              Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

              1 Reply Last reply
              0
              • K Offline
                K Offline
                KA51O
                wrote on last edited by
                #7

                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

                • "link2":http://stackoverflow.com/questions/6843247/problems-with-qobject-multiple-inheritance-and-policy-traits-design-in-c

                • "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.")

                1 Reply Last reply
                0
                • R Offline
                  R Offline
                  rubikon
                  wrote on last edited by
                  #8

                  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_OBJECT

                  public:
                  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]

                  1 Reply Last reply
                  0
                  • K Offline
                    K Offline
                    KA51O
                    wrote on last edited by
                    #9

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

                    1 Reply Last reply
                    0
                    • R Offline
                      R Offline
                      rubikon
                      wrote on last edited by
                      #10

                      This really seems to work :-) Thank you very very much!!

                      1 Reply Last reply
                      0
                      • K Offline
                        K Offline
                        KA51O
                        wrote on last edited by
                        #11

                        Glad I could help. If you could please edit your first post and prepend [SOLVED] to the title.

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved