Was mach das Makro Q_D()?

Alles rund um die Programmierung mit Qt
Antworten
kugelfisch
Beiträge: 12
Registriert: 28. Juni 2006 23:37
Wohnort: Kalrsuhe
Kontaktdaten:

Was mach das Makro Q_D()?

Beitrag von kugelfisch »

Hallo,

kann mir jemand erklähren, was Q_D() macht? Von welchem Typ ist die Variable "d" in QModelDir ?


QModelDir.cpp

Code: Alles auswählen

QDirModel::QDirModel(const QStringList &nameFilters,
                     QDir::Filters filters,
                     QDir::SortFlags sort,
                     QObject *parent)
    : QAbstractItemModel(*new QDirModelPrivate, parent)
{
    Q_D(QDirModel);
    
    // we always start with QDir::drives()
    d->nameFilters = nameFilters.isEmpty() ? QStringList("*") : nameFilters;
    d->filters = filters;
    d->sort = sort;
    d->root.parent = 0;
    d->root.info = QFileInfo();
    d->clear(&d->root);
}

qglobal.h

Code: Alles auswählen

#define Q_DECLARE_PRIVATE(Class) \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } \
    friend class Class##Private;


#define Q_D(Class) Class##Private * const d = d_func()

Gruß
Alex[/code]
kugelfisch
Beiträge: 12
Registriert: 28. Juni 2006 23:37
Wohnort: Kalrsuhe
Kontaktdaten:

Beitrag von kugelfisch »

Ah ich glaub ich habs. d ist ein Pointer auf eine Instanz der Klasse QDirModelPrivate - richtig?

Aber wo steckt da der Sinn dahinter?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Der sinn ist einfach - mann muss nicht so viel schreiben - Q_D() wird überall im Qt-Code verwendet. So weiss man immer gleich was gemeint ist.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Eltharion
Beiträge: 74
Registriert: 4. Mai 2006 14:42
Wohnort: Magdeburg
Kontaktdaten:

Beitrag von Eltharion »

Ich glaube, es war die Frage nach dem Sinn der Trennung in Klassen und zugehörige Private-Klassen. Ich versuche mal eine Antwort zu geben, obwohl ich dabei sicherlich auch Fettnäpfchen erwischen werde. Ich bitte um eine rege, objektive Diskussion.

Einen wirklichen Sinn der ...Private-Klassen gibt es nicht, da man eigentlich auch via public/protected/private die Zugriffsrechte für Qt-interne Dinge setzen könnte. So wird die (Qt)Klasse zusätzlich noch in einen Private-Part und einen offiziellen Part geteilt und das ist m.E. nicht so toll, da man an die Private-Sachen später (ausserhalb von Qt) nicht mehr (oder nur noch sehr schlecht) ran kommt. Die Klasse wird API-mässig fixiert und ist später durch einfaches Ableiten oft nicht mehr sinnvoll erweiterbar. Die Erfinder wollten damit wohl verhindern, dass man in eigenen Programmen auf Qt-interne Daten oder Methoden zugreift oder zugreifen möchte. Normalerweise muss man das auch nicht, aber es gibt Situationen, wo man das schön wäre und ärgert sich dann darüber.

Man leitet z.B. eine Qt-Klasse ab und möchte ein exotischeres Feature dieser Klasse erweitern oder abändern und stellt fest, dass die zugehörigen Methoden der Qt-Klasse wiederum mit einer Klasse/Instanz namens QXyzPrivate interagieren, was die QXyz-Klasse problemlos darf, die davon abgeleitete Klasse aber nicht mehr. Das wird absolut nervig, wenn mehrere Klassen im Spiel sind, die sich gegenseitig aufrufen (oder wo eine Klasse eine Instanz der anderen erzeugt) oder sich gegenseitig via friend Rechte einräumen.

Damit erlauben die Trolltech-Programmierer zwar die Nutzung Ihrer Klassen, aber blockieren effizient die Erweiterung der API und die Erweiterung der Funktionalität der eigenen Klassen. Man versuche nur mal, z.B. die QTabBar um Drag- und Drop-Funktionen für Tabs oder um Interaktionen (Loslösen und Fallenlassen) von Tab-Inhalten und DockWindows zu erweitern. Wäre toll, wenn das einfach so ginge, aber man wird bei der Implementation durch die Trennung der API-Funktionen und der internen Hilfs-Funktionen dazu gezwungen, die Klassen zu nehmen und neu zu implementieren. Unter einem neuen Klassen-Namen und möglichst auch mit völlig neuem Code. Wiederverwertung von Code durch Ableiten wird unterbunden und ist nur den Trollen selbst erlaubt. Andere haben gefälligst das Rad neu zu erfinden oder grosse Teile der Klassen zu kopieren und dadurch auf die Vorteile der OO-Programmierung zu verzichten.

Für die Programmierer bringt es keine Vorteile. Einzig der Nutzer kann sich zufrieden zurücklehnen, denn wo z.B. Qt4 dran steht, ist auch Qt4 drin und ein Qt4-Programm kann problemlos gegen Qt4-Libs gelinkt werden. Der Programmierer muss das ausbaden. Der Sinn ist denke ich das Verhindern des Entstehens von Konkurrenz-Bibliothekten durch Verbesserung der eigenen Bibliothek, es ist also quasi ein Kopierschutz, der hart in den Quelltext eingebaut ist und das Aufkommen von Konkurrenz (durch bessere Qt-Ableger) welche auf der eigenen (aus Troll-Sicht) Arbeit (im Wesentlichen der Qt-Lib) basiert, verhindert.

Wenn man es genau nimmt, wird dadurch sogar der Quelltext aufgeblähter, unaufgeräumter/undurchschaubarer (mehr Einarbeitezeit, neue interne Makros, nicht wirklich notwendige ..Private-Klassen) und ineffizienter (da tlw. Aufrufe von Methoden einer Klasse an die der ..Private-Klasse weitergeleitet werden). Alles unnützer Kram, der bei einer konsequent-freien Implementierung entfallen könnte.

Einen Vorteil für den Nutzer der Klassen sehe ich, denn dieser wird in der Hilfe und beim Auto-Vervollständigen mittels Tab von vielen Optionen verschont und kann daher schneller seine Auswahl treffen, da die Anzahl der Methoden und Features abnimmt. Das könnte man aber mit einer guten Namenswahl der Funktionen auch erreichen.

E*
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Ein weiterer Vorteil ist, dass man im Header ggf. weniger Includes braucht und dass man bei Änderungen an einer privaten Varaible (z.B. hinzufügen/entfernen) nicht alles neu kompilieren muss was diesen Header includiert
-> das Kompilieren geht schneller.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Uwe
Beiträge: 176
Registriert: 9. Oktober 2005 13:37
Wohnort: München

Beitrag von Uwe »

Christian81 hat geschrieben:Ein weiterer Vorteil ist, dass man im Header ggf. weniger Includes braucht und dass man bei Änderungen an einer privaten Varaible (z.B. hinzufügen/entfernen) nicht alles neu kompilieren muss was diesen Header includiert
-> das Kompilieren geht schneller.
Es geht natürlich auch um die Binärkompatibilität der Qt Bibliothek. Bei Änderungen im Private Teils zerbricht die nicht.

Der Performance Gewinn mit schlanken Header ist übrigens erheblich. Ich erinnere mich an die Portierung einer Applikation von Qt1 nach Qt2, bei der die Übersetzungszeiten von ca. 7 Minuten auf über 20 Minuten hochgingen. Die Qt3 Header waren diesbezüglich ebenfalls schlecht entworfen: mit ein paar Patches konnte man die Übersetzungszeiten deutlich senken.

Erst mit Qt4 hat TrollTech dieses Problem ernsthaft verfolgt und die Übersetzungszeiten sind wieder deutlich besser.

Uwe
Antworten