ABC-Interface mit signals

Alles rund um die Programmierung mit Qt
Antworten
micha.specht
Beiträge: 3
Registriert: 20. Februar 2009 22:34

ABC-Interface mit signals

Beitrag von micha.specht »

Hallo,

ich möchte gern ein Interface I als abstrakte Basisklasse (ABC) definieren, das neben ein paar Methodendeklarationen auch signals beinhaltet. Dazu muss I von QObject erben, weil QObject ja die Grundlage für signals und slots ist (und connect auch nur zwei QObjects miteinander verbinden kann).

Desweiteren gibt es eine Basisklasse A, von der zwei Subklassen B und C erben. B und C bauen auf der Funktionalität von A auf und sollen zusätzlich I implementieren.

Das Problem ist, dass sowohl A als auch I von QObject erben müssen, der Compiler beschwert sich dann bei B und C, dass man nicht zweimal von QObject erben kann.

Also das ganze nochmal als Übersicht:

Code: Alles auswählen

class I: public QObject; // abstrakte Basisklasse

class A: public QObject; // Basisklasse

class B: public A, public I; // eine Klasse, die I implementieren soll
class C: public A, public I; // eine weitere Klasse, die I implementieren soll
Ich habe jetzt die Signale von I in A verschoben, und I nicht mehr von QObject erben lassen, das ist aber natürlich Unsinn, und deshalb meine Frage: Gibt es eine Möglichkeit, dass ein Interface auch signals bereitstellen kann? Ich möchte nämlich, wenn ich ein I bekomme, direkt die Signale abfangen und nicht noch in A, B, oder C casten müssen (dafür sind Interfaces ja da).

Vielen Dank,
Micha.
The User
Beiträge: 62
Registriert: 11. Dezember 2008 23:48

Beitrag von The User »

Wenn du in A, B oder C casten würdest, würdest du die ganze Flexibilität der Vererbung verlieren. Allerdings unterstützt QObject auch keine mehrfache virtuelle Vererbung (ebenso wenig wie Template-Klassen :( ). Du musst also casten, allerdings in QObject& oder QObject*. connect kannst du ja mit jedem beliebigen aufrufen. Ich habe mal ein Beispiel gemacht, allerdings ohne Qt, denk dir einfach Base als QObject:

Code: Alles auswählen

#include <iostream>
#include <stdexcept>
#include <typeinfo>
using namespace std;

class Interface
{
	public:
		virtual void changed() = 0;
};

class Base
{
    public:
        int x;
        void test()
        {
            cout << "Foo Bar " << x << endl;
        }
};

class Child : public Interface, public Base
{
    public:
        void changed()
        {
            cout << "changed" << endl;
        }
};

void testRef(Interface& i) throw(bad_cast)
{
    i.changed();
    Base& b = dynamic_cast<Base&>(i);
    b.test();
}

void testPtr(Interface* i) throw(invalid_argument)
{
    i->changed();
    if(Base* b = dynamic_cast<Base*>(i))
        b->test();
    else
        throw invalid_argument("testPtr needs a Base");
}

int main()
{
    Child c;
    c.x = 12;
    testRef(c);
    testPtr(&c);
}
Viele liebe Grüße
The User
Antworten