2

How to define signals in interfaces?

class ISomeInterface
{
    signals:
        virtual void added(const QString& id) = 0;
        virtual void removed(const QString& id) = 0;

    // bla, other methods
}

Afaik, signals should not virtual but if I want to define that a signal needs to be implemented in classes implementing the interface => how to do this? Or do you simply make them non-abstract... but interfaces have no Q_OBJECT declaration here! Is the correct code generated in this cases? On top... you'll need a bad (f***g) cast to QObject if you want to connect to the signals.

class ISomeInterface
{
    signals:
        void added(const QString& id);
        void removed(const QString& id);

    // bla, other methods
}

Or do you try to implement it that way?

class ISomeInterface : public QObject
{
    Q_OBJECT

    signals:
        void added(const QString& id);
        void removed(const QString& id);

    // bla, other methods
}

Q_DECLARE_INTERFACE(ISomeInterface, "ISomeInterface")

.. but this way I can inherit from only one interface (QObject does not support multiple inheritance).

Conclusion: As suggested, I would go with the first one.

Beachwalker
  • 7,685
  • 6
  • 52
  • 94

2 Answers2

3
  1. Define signals as virtual abstract protected methods. (Instead of protected you may use signal: keyword).
  2. Final object must interhit your interface and QObject
  3. Cast pointer to interface to QObject * with dynamic_cast
  4. Connect pointer to necessary slots

You may check this topic for some solutions.

Community
  • 1
  • 1
Dmitry Sazonov
  • 8,801
  • 1
  • 35
  • 61
2

Unfortunately Qt does not handle multiple inheritance from QObject (see this Q&A), so you can't derive all your interfaces from it (otherwise you won't be able to derive from multiple interfaces). So instead you might have something like IQObject interface with

virtual QObject* qObject() = 0

method, so you don't need to cast them to QObject all the time.

As for providing interface for signals - no such thing. What you can do is make them virtual abstract, that'll work if you really need to enforce this compile-time check (because signals: is just an alias for protected:). If you don't, just check the return value from the connect() method.

Community
  • 1
  • 1
spiritwolfform
  • 2,263
  • 15
  • 16
  • 1
    The `qObject` method is guaranteed to outperform `dynamic_cast(pInterface)` and thus is a good idea. There are no guarantees about `dynamic_cast`'s complexity, while `qObject` has a constant cost. The implementation `QObject * MyClass::qObject() { return this; }` amounts to simple pointer arithmetic. – Kuba hasn't forgotten Monica Mar 29 '17 at 20:41