Interfaces and Abstract classes



  • Hi

    I've just started writing a prototype to find out how certain things work in c++11/qt5. I've noticed that at least in c++ there is no keyword to achieve interfaces or abstract classes but one uses virtual methods instead.

    [code]
    virtual void setValue (QString s) = 0;
    [/code]

    Qt seems to have a macro called something like Q_DEFINE_INTERFACE or something. But i'm not able to find any usable examples.

    So due to the lack of documentation i'm not sure if i'm doing it the right way. Since it is easy to run into problems later on i would like to hear some opinions about my approach.

    interface: [code]
    #ifndef ICONTROLLABLE_H
    #define ICONTROLLABLE_H

    #include <QObject>

    class IControllable
    {
    public:
    //explicit IControllable(QObject *parent = 0);
    virtual ~IControllable () {}
    virtual void start () = 0;
    virtual void stop () = 0;
    virtual void show () = 0;
    virtual void hide () = 0;
    };

    #endif // ICONTROLLABLE_H
    [/code]

    abstract base class: [code]
    #ifndef PLAYERBASE_H
    #define PLAYERBASE_H

    #include <QObject>

    class PlayerBase : public QObject
    {
    Q_OBJECT
    public:
    QString source;

    explicit PlayerBase(QObject *parent = 0);
    virtual void setSource (QString source) = 0;

    signals:
    void playbackFinished (QString source);

    };

    #endif // PLAYERBASE_H
    [/code]

    concrete class: [code]
    #ifndef VIDEOPLAYER_H
    #define VIDEOPLAYER_H

    #include <QObject>
    #include "playerbase.h"

    class videoPlayer : public PlayerBase
    {
    Q_OBJECT
    public:
    videoPlayer();
    };

    #endif // VIDEOPLAYER_H

    [/code]

    So how is it. Should my interface inherit form QObject too? Should i run the base (supercalss) constructor?
    May it be a problem that each of these classes inherit from QObject themselves?

    It would be nice if you could clarify my questions with some example code. I don't really know yet how i run the super constructor for example.



  • You define an interface for use with QObject just like any other interface, defining a class consisting only of pure virtual methods and additionally provide some meta information for the Qt meta object compiler:
    @
    // IMyInterface.h

    #ifndef IMYINTERFACE_H
    #define IMYINTERFACE_H

    #include <QtPlugin>

    class IMyInterface
    {

    public:
    virtual void doSomething() = 0;
    virtual void doSomethingElse() = 0;

    };

    #define MyInterface_iid "com.acme.MyInterface"

    Q_DECLARE_INTERFACE(IMyInterface, MyInterface_iid)

    #endif // IMYINTERFACE_H
    @

    To implement the interface you inherit it with a class derived from QObject and tell the meta object compiler about the implemented interfaces using Q_INTERFACES:

    @
    // MyClass.h

    #ifndef MYCLASS_H
    #define MYCLASS_H

    #include "IMyInterface.h"

    #include <QtCore/QObject>

    class MyClass : public QObject, public IMyInterface
    {

    Q_OBJECT

    Q_INTERFACES(IMyInterface)

    public:
    void doSomething();
    void doSomethingElse();

    };

    #endif // MYCLASS_H
    @

    The Qt meta object compiler will add the information about implemented interfaces to the meta object for your class. You can then use qobject_cast to test for implemented interfaces just like you would normally with dynamic_cast, but without it's drawbacks:

    @
    IMyInterface* myInterface = qobject_cast<IMyInterface*>(object);
    if (myInterface) {
    // Object implements interface
    }
    @

    It should be noted that Qt/C++ is a lot less strict than e.g. Java, so your "interface" class may also be an abstract class containing implementations.



  • Thanks for this great reply. I will try this right now!

    So abstract classes and interfaces are basically the same. Should is also Q_DECLARE_INTERFACE for my abstract classes?
    => probably Q_DECLARE_METATYPE. Is there any documentation about all this DECLARE macros?

    My abstract class BasePlayer inherits from QObject and therefore has the Q_OBJECT macro as first statement. Does my ConcretePlayer which inherits from BasePlayer also needs to declare this macro?
    => the answer seems to be 'no' since i get an error when i do this.

    [code]
    #ifndef VIDEOPLAYER_H
    #define VIDEOPLAYER_H

    #include <QQmlEngine>
    #include "playerbase.h"
    #include "icontrollable.h"
    #include "iplaceable.h"

    class VideoPlayer : public PlayerBase, public IControllable, public IPlaceable
    {
    Q_INTERFACES(IControllable)
    Q_INTERFACES(IPlaceable)
    public:
    explicit VideoPlayer (QObject *parent = 0, QQmlEngine *engine = 0);

    // PlayerBase members
    virtual void setSource (QString source);

    // IControllable members
    virtual void start ();
    virtual void stop ();
    virtual void show ();
    virtual void hide ();

    // IPlaceable members
    virtual void setGeometry (int x, int y, int width, int height);

    private:
    QString source;
    int x, y, width, height;
    };

    #endif // VIDEOPLAYER_H
    [/code]



  • bq. So abstract classes and interfaces are basically the same.

    Interfaces in C++ are a concept rather than a language construct like in other languages. The same goes for abstract classes, so you could say that, yes. C++ does not know about interfaces or abstract classes, but the language feature of pure virtual methods allows you to use these concepts.

    bq. Should is also Q_DECLARE_INTERFACE for my abstract classes?

    No, not in general - it depends on your use case. Most of the time you will want to restrict the use of this technique to interfaces only, but it may be useful once in a while to add predefined functionality through an abstract class. Interfaces are most helpful when you want to implement additional capabilities not provided by any base class of your class. On a semantic level you could say that regular inheritance describes an "is a ..." relation, while the use of an interface should be more like "is capable of ..." or "can do ...". The power of interfaces is that you can add optional capabilities to classes and query for them at runtime.

    bq. => probably Q_DECLARE_METATYPE. Is there any documentation about all this DECLARE macros?

    Q_DECLARE_METATYPE is something entirely different. You would mark a class of yours as meta type if you intend to use it as a possible QVariant value or as parameter for signal-slot-connections. The Qt documentation does contain information on both "Q_DECLARE_METATYPE":http://qt-project.org/doc/qt-5.0/qtcore/qmetatype.html#Q_DECLARE_METATYPE and "Q_DECLARE_INTERFACE":http://qt-project.org/doc/qt-5.0/qtcore/qtplugin.html#Q_DECLARE_INTERFACE.

    bq. My abstract class BasePlayer inherits from QObject and therefore has the Q_OBJECT macro as first statement. Does my ConcretePlayer which inherits from BasePlayer also needs to declare this macro?

    It only needs to when you intend to define signals, slots, properties or implemented interfaces in your ConcretePlayer class.



  • [quote author="Arnold Konrad" date="1367248562"]bq. So abstract classes and interfaces are basically the same.

    Interfaces in C++ are a concept rather than a language construct like in other languages. The same goes for abstract classes, so you could say that, yes. C++ does not know about interfaces or abstract classes, but the language feature of pure virtual methods allows you to use these concepts.
    [/quote]

    I would define that that a bit more specific:

    An interface in C++ is a pure virtual class without constructor or destructor and without any implemented method.

    A abstract class is any class that has at least one pure virtual method (but might have implementation for other methods).



  • bq. So abstract classes and interfaces are basically the same.

    Officially, there are no interfaces in C++. You can use an abstract class in the context of an interface just as you can use a regular, non-abstract class. The difference is abstract classes cannot be instantiated on their own and do not provide any default implementation and force you to specify it.



  • They already told you how to mimic "interfaces" in c++, I would
    like to give you my small advices(you don't need to follow it).
    If you are coming from c# or java or other languages, pick a good book
    of c++ and study it before you develop any app with c++ and Qt. "C++ primer 5" is an ideal book for beginners if you are a diligent one and have enough of time to study it.If you want to catch up to c++ in a very short time, try "essential c++"(I don't know there are a new version for c++11 or not).

    Better don't try the way of "everything is object" when designing your apps with c++.Everybody told me "a good programmer should be able to learn new things", but I would like to say, "a good programmer should be able to unlearn too".A good style in language XX may be a disaster in language YY, and new techs may make old techs become deprecated, that is why we need to know how to "unlearn".



  • Thanks for this advice. Unfortunately i do not have time to study a book before beginning. My schedule is really tight.

    I try to design my software as modular as possible so a can refactor it easaly later on.



  • Well, modular software doesn't really go well with "no time to study a book before beginning" - following intuition alone newcomers tend to do quite the contrary - make extremely non-modular design absent knowledge of the language and its paradigms.

    C++ is a BIG language, especially since c++11 - the good news is you will hardly ever need to use more than 1/10 of the language, and most of that stuff you should already know if you've developed in another language, in that case what you really need to do is sit down and go through a "differences between myOldLanguage and C++" article to quickly learn the C++ specifics.

    Good news is with Qt you can get very good modularity and separation, as well as a healthy productivity boost if you decide to adopt QML as structural and glue language.



  • Yes. Im not new to programming and the design process is going well. The problem is that i just don't get enough time for a clean solution ans so i'm forced doing only "a" solution and live with it.

    But i will look into the books mentioned above. A quick look can't do any harm.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.