 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Markus Zimmermann Guest
|
Posted: Wed Mar 30, 2005 9:00 pm Post subject: Frage zu Klassendesign |
|
|
Hallo,
in Qt gibt es eine Klasse QDataTable. In dieser Klasse wird verkürzt
folgendes gemacht:
class QDataTable : public QTable
{
public:
//Reihe von Variablen
protected:
//Reihe von Variablen
private:
//Reihe von Variablen UND
QDataTablePrivate* d;
};
In der cpp-Datei wird dann vor den Implementierungen der Member-Funktionen
von QDataTable eine Klasse QDataTablePrivate definiert. Etwa so:
class QDataTablePrivate
{
public:
//Menge von Variablen (davon nur zwei Zeiger, keine Elementfunktionen)
};
Der Konstruktor von QDataTable ruft dann eine Funktion init() auf:
void QDataTable::init()
{
d = new QDataTablePrivate();
setAutoEdit( TRUE );
setSelectionMode( SingleRow );
setFocusStyle( FollowStyle );
d->trueTxt = tr( "True" );
d->falseTxt = tr( "False" );
d->datefmt = Qt::LocalDate;
reset();
connect( this, SIGNAL( selectionChanged() ),
SLOT( updateCurrentSelection()));
}
Was bringt die Vorgehensweise? Warum schreiben die Programmierer von
Trolltech die in QDataTablePrivate definierten Variablen nicht gleich in
den private-Bereich von QDataTable? Warum erzeugen Sie ein dynamisches
Objekt der QDataTablePrivate-Klasse?
Danke.Markus
--
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Friedhelm Hoerner Guest
|
Posted: Thu Mar 31, 2005 5:36 am Post subject: Re: Frage zu Klassendesign |
|
|
Markus Zimmermann <Markus.Zimmermann (AT) hz-bau (DOT) de> wrote
| Quote: | Hallo,
in Qt gibt es eine Klasse QDataTable. In dieser Klasse wird verkürzt
folgendes gemacht:
class QDataTable : public QTable
{
public:
//Reihe von Variablen
protected:
//Reihe von Variablen
private:
//Reihe von Variablen UND
QDataTablePrivate* d;
};
In der cpp-Datei wird dann vor den Implementierungen der Member-Funktionen
von QDataTable eine Klasse QDataTablePrivate definiert. Etwa so:
class QDataTablePrivate
{
public:
//Menge von Variablen (davon nur zwei Zeiger, keine Elementfunktionen)
};
Der Konstruktor von QDataTable ruft dann eine Funktion init() auf:
void QDataTable::init()
{
d = new QDataTablePrivate();
[...]
}
Was bringt die Vorgehensweise? Warum schreiben die Programmierer von
Trolltech die in QDataTablePrivate definierten Variablen nicht gleich in
den private-Bereich von QDataTable? Warum erzeugen Sie ein dynamisches
Objekt der QDataTablePrivate-Klasse?
|
Das ist eine sogenannte "Compilation Firewall" auch unter dem
Stichwort "pimpl" = Pointer to Implementation bekannt. Damit wirken
sich Änderungen in der Implementierung (QDataTablePrivate) in keiner
Weise auf andere Quelltexte aus.
Im Headerfile (z.B.QDataTable.hpp) ändert sich garnichts, wenn sich in
der Implementierungsklasse etwas ändert (z.B neue Membervariablen
hinzugefügt oder entfernt werden). Und damit kann man das erneute
Compilieren aller Programme die QDataTable verwenden vermeiden.
Außerdem können Details der Implementierung komplett vor dem Nutzer
der Bibliothek versteckt werden.
Private member sind zwar dem Zugriff verborgen, nicht jedoch dem
Einblick;-)
Und das kann zum einen Implementierungsdetails verraten, und schafft
zum anderen eben unerwünschte Abhängigkeit beim Compilieren.
Gruss Friedhelm
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Rene Moehring Guest
|
Posted: Thu Mar 31, 2005 7:00 am Post subject: Re: Frage zu Klassendesign |
|
|
On 30 Mar 2005 21:36:07 -0800, Friedhelm Hoerner wrote:
| Quote: | Markus Zimmermann <Markus.Zimmermann (AT) hz-bau (DOT) de> wrote
[OT-Pimpl]
Das ist eine sogenannte "Compilation Firewall" auch unter dem
Stichwort "pimpl" = Pointer to Implementation bekannt. Damit wirken
sich Änderungen in der Implementierung (QDataTablePrivate) in keiner
Weise auf andere Quelltexte aus.
Im Headerfile (z.B.QDataTable.hpp) ändert sich garnichts, wenn sich in
der Implementierungsklasse etwas ändert (z.B neue Membervariablen
hinzugefügt oder entfernt werden). Und damit kann man das erneute
Compilieren aller Programme die QDataTable verwenden vermeiden.
Außerdem können Details der Implementierung komplett vor dem Nutzer
der Bibliothek versteckt werden.
Private member sind zwar dem Zugriff verborgen, nicht jedoch dem
Einblick;-)
Und das kann zum einen Implementierungsdetails verraten, und schafft
zum anderen eben unerwünschte Abhängigkeit beim Compilieren.
|
Sagt mal, ist es eigentlich günstiger den Pimpl so zu realisieren wie in
dem QT-Beispiel oder wäre es besser aus dem impl-struct ne komplette
Klasse zu machen, die die eigentlichen Memberfunktionen hat und zu denen
delegiert werden würde?
Beispiel:
A::foo()
{
pimpl_->foo();
}
--
I'm not a racist. I hate everyone equally!
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Thorsten Nitz Guest
|
Posted: Thu Mar 31, 2005 8:38 am Post subject: Re: Frage zu Klassendesign |
|
|
Rene Moehring schrieb:
| Quote: | On 30 Mar 2005 21:36:07 -0800, Friedhelm Hoerner wrote:
Markus Zimmermann <Markus.Zimmermann (AT) hz-bau (DOT) de> wrote
[OT-Pimpl]
|
Obs wirklich OT ist? Ich halte es für ein C++-Idiom, das in anderen
Sprachen so nicht benutzt wird.
[hier: Implementierung ohne Memberfunktionen]
| Quote: | Das ist eine sogenannte "Compilation Firewall" auch unter dem
Stichwort "pimpl" = Pointer to Implementation bekannt. Damit wirken
sich Änderungen in der Implementierung (QDataTablePrivate) in keiner
Weise auf andere Quelltexte aus.
Sagt mal, ist es eigentlich günstiger den Pimpl so zu realisieren wie in
dem QT-Beispiel oder wäre es besser aus dem impl-struct ne komplette
Klasse zu machen, die die eigentlichen Memberfunktionen hat und zu denen
delegiert werden würde?
|
Wenn Du an Interfaces glaubst, ist es günstig, in der außen sichtbaren
Klasse nur public-Elemente zu haben, mit Ausnahme des pimpl-Zeigers.
// A.h
class AImpl; // Vorwärtsdeklaration, gibt nichts über die Klasse preis
class A {
private:
AImpl *pimpl;
public:
// Ab hier öffentliche Schnittstelle
void foo();
A();
};
// A.cpp
A::A()
{ pimpl = new AImpl;
// weitere Initialisierungen
}
void A::foo()
{
pimpl->foo(); // reine Delegation
}
class AImpl {
// ... Hier passiert die eigentliche Arbeit
}
Hier habe ich Deinen Vorschlag der Delegation ebenfalls verwendet. Da
der Inhalt von A.cpp aber schon vor den Benutzern der Klasse A verborgen
ist, ist es nicht notwendig, dass AImpl die Schnittstelle von A eins zu
eins nachbaut. Die Methoden von A können also schon Algorithmen
enthalten, ohne dass die Kapselung verletzt wäre. Es bietet sich z.B.
an, in A schon Plausibilitätsprüfungen für Parameterwerte vorzunehmen,
oder Memberfunktionen zu implementieren, die auf der Basis anderer
öffentlicher Member implementiert werden können. Manche meinen
allerdings, es sei ein Designfehler, solche Funktionen überhaupt in die
Schnittstelle aufzunehmen.
Wesentlich ist, dass der Inhalt von A.h minimalistisch und stabil ist.
Tschö, wa!
Thorsten
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Thu Mar 31, 2005 9:17 am Post subject: Re: Frage zu Klassendesign |
|
|
"Thorsten Nitz" <T.Nitz (AT) epost (DOT) de> schrieb im Newsbeitrag
news:424bb707$1 (AT) news (DOT) ginko.net...
| Quote: | Rene Moehring schrieb:
Wenn Du an Interfaces glaubst, ist es günstig, in der außen sichtbaren
Klasse nur public-Elemente zu haben, mit Ausnahme des pimpl-Zeigers.
// A.h
class AImpl; // Vorwärtsdeklaration, gibt nichts über die Klasse preis
class A {
private:
AImpl *pimpl;
public:
// Ab hier öffentliche Schnittstelle
void foo();
A();
};
|
Man kann die Vorwärtsdeklaration auch gleich in die private-Sektion von A
einbauen:
class A{
private:
class AImpl;
AImpl* pimpl;
};
Damit wird explizit ausgedrückt, wem AImpl gehört. Es kann auch einen
Unterschied bei tools wie Klassenbrowsern, Auto-Dokumentationen etc. machen,
ob andere AImpl dann überhaupt zu Gesicht bekommen.
Alternativ bietet sich auch ein Extranamespace (namespace impl{} etc.) an.
Ich finde beides sauberer, als die Deklaration einfach in den selben Raum zu
stellen wie die eigentliche zu benutzende Klasse
Thomas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Rene Moehring Guest
|
Posted: Thu Mar 31, 2005 1:30 pm Post subject: Re: Frage zu Klassendesign |
|
|
On Thu, 31 Mar 2005 10:38:02 +0200, Thorsten Nitz wrote:
| Quote: | Rene Moehring schrieb:
On 30 Mar 2005 21:36:07 -0800, Friedhelm Hoerner wrote:
Markus Zimmermann <Markus.Zimmermann (AT) hz-bau (DOT) de> wrote
[OT-Pimpl]
Obs wirklich OT ist? Ich halte es für ein C++-Idiom, das in anderen
Sprachen so nicht benutzt wird.
[hier: Implementierung ohne Memberfunktionen]
|
Ich meinte eigentlich QT - war ein kleiner Vertipper.
| Quote: |
Das ist eine sogenannte "Compilation Firewall" auch unter dem
Stichwort "pimpl" = Pointer to Implementation bekannt. Damit wirken
sich Änderungen in der Implementierung (QDataTablePrivate) in keiner
Weise auf andere Quelltexte aus.
Sagt mal, ist es eigentlich günstiger den Pimpl so zu realisieren wie in
dem QT-Beispiel oder wäre es besser aus dem impl-struct ne komplette
Klasse zu machen, die die eigentlichen Memberfunktionen hat und zu denen
delegiert werden würde?
Wenn Du an Interfaces glaubst, ist es günstig, in der außen sichtbaren
Klasse nur public-Elemente zu haben, mit Ausnahme des pimpl-Zeigers.
// A.h
class AImpl; // Vorwärtsdeklaration, gibt nichts über die Klasse preis
class A {
private:
AImpl *pimpl;
public:
// Ab hier öffentliche Schnittstelle
void foo();
A();
};
// A.cpp
A::A()
{ pimpl = new AImpl;
// weitere Initialisierungen
}
void A::foo()
{
pimpl->foo(); // reine Delegation
}
class AImpl {
// ... Hier passiert die eigentliche Arbeit
}
Hier habe ich Deinen Vorschlag der Delegation ebenfalls verwendet. Da
der Inhalt von A.cpp aber schon vor den Benutzern der Klasse A verborgen
ist, ist es nicht notwendig, dass AImpl die Schnittstelle von A eins zu
eins nachbaut. Die Methoden von A können also schon Algorithmen
enthalten, ohne dass die Kapselung verletzt wäre. Es bietet sich z.B.
an, in A schon Plausibilitätsprüfungen für Parameterwerte vorzunehmen,
oder Memberfunktionen zu implementieren, die auf der Basis anderer
öffentlicher Member implementiert werden können. Manche meinen
allerdings, es sei ein Designfehler, solche Funktionen überhaupt in die
Schnittstelle aufzunehmen.
Wesentlich ist, dass der Inhalt von A.h minimalistisch und stabil ist.
|
Also ist es im Grunde egal.
--
I'm not a racist. I hate everyone equally!
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|