 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
helmut.weil@t-online.de Guest
|
Posted: Wed Dec 13, 2006 4:04 pm Post subject: Interna der Klasse in Header-Datei vor Benutzer verbergen |
|
|
Hallo
Wie kann ich die Schnittstelle einer Klasse in einer Header-Datei
veröffentlichen, und trotzdem die Interna Klasse vor dem Benutzer
verbergen:
--------------------------------------------------------
//Normale Header-Datei als Grundlage meiner Implementierung
class A{
int a;
void geheim(int);
public:
A(int = 0);
void offen(int);
};
--------------------------------------------------------
//Gewünschte Header-Datei für den Nutzer der Klasse
class A{
public:
A(int = 0);
void offen(int);
};
--------------------------------------------------------
Muss ich 2 Header-Dateien schreiben (ziemlicher Aufwand, die beiden
synchron zu halten) oder gibt es eine elegantere Lösung.
Gruss
Helmut |
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Wed Dec 13, 2006 11:58 pm Post subject: Re: Interna der Klasse in Header-Datei vor Benutzer verberge |
|
|
"helmut.weil@t-online.de" <helmut.weil@t-online.de> writes:
| Quote: | Wie kann ich die Schnittstelle einer Klasse in einer Header-Datei
veröffentlichen, und trotzdem die Interna Klasse vor dem Benutzer
verbergen:
|
Mit dem "pimpl-Idiom". Siehe
http://www.gotw.ca/gotw/024.htm
http://www.gotw.ca/gotw/028.htm |
|
| Back to top |
|
 |
Martin Winkler Guest
|
|
| Back to top |
|
 |
Jörg Barfurth Guest
|
Posted: Thu Dec 14, 2006 2:31 am Post subject: Re: Interna der Klasse in Header-Datei vor Benutzer verberge |
|
|
helmut.weil@t-online.de schrieb:
| Quote: | Hallo
Wie kann ich die Schnittstelle einer Klasse in einer Header-Datei
veröffentlichen, und trotzdem die Interna Klasse vor dem Benutzer
verbergen:
|
Einen Hinweis of die Antwort (pimpl-Idiom) hast du ja schon von Anderen
bekommen.
Eine Warnung aber tut noch not:
| Quote: | --------------------------------------------------------
//Normale Header-Datei als Grundlage meiner Implementierung
class A{
int a;
void geheim(int);
public:
A(int = 0);
void offen(int);
};
--------------------------------------------------------
//Gewünschte Header-Datei für den Nutzer der Klasse
class A{
public:
A(int = 0);
void offen(int);
};
--------------------------------------------------------
Muss ich 2 Header-Dateien schreiben (ziemlicher Aufwand, die beiden
synchron zu halten)
|
Nein! Du darfst nur eine Definition der Klasse in deinem Programm haben.
Oder genau genommen: alle Definitionen einer Klasse in deinem Programm
müssen identisch sein. Das erreichst du am einfachsten, indem du diese
Definition an genau eine Stelle schreibst (in einen Header) und diesen
Definitionstext jedes Mal per #include einbindest wenn du eine
Definition der Klasse brauchst. (Formell hast du damit mehrere
Definitionen, die aber alle gleich sind.)
Wenn du unterschiedliche Definitionen für eine Klasse in einem Programm
verwendest, dann erhältst du undefiniertes Verhalten. In deinem Fall
würde z.B. beim Anlegen eines Objektes der Klasse A (ob statisch,
automatisch oder dynamisch) bei Sichtbarkeit der zweiten Definition
*kein* Platz für das Datenmember A::a reserviert. Wenn nun eine
Memberfunktion auf das vermeintliche Member, gemäß der anderen
Definition, zugreift, kann alles mögliche Unheil geschehen. Es gibt noch
jede Menge andere Dinge die schief laufen können, wenn verschiedene
Deklarationen einer Klasse Objekte verschiedener Größe beschreiben. Doch
auch andere Unterschiede zwischen Deklarationen können auf subtile Weise
zu Fehlern führen. Also wie immer bei undefiniertem Verhalten: lass es sein.
| Quote: | oder gibt es eine elegantere Lösung.
|
Leider nur das pimpl-Idiom. Manchmal kann das Overkill sein kann, aber
wenn du gute Gründe hast die Klasseninterna zur Compilezeit zu
verbergen, dann ist es das Mittel der Wahl in C++.
Es gibt da auch noch ein paar Variationen. Zum Beispiel kannst du
manchmal eine Fassadenklasse benutzen, die ein ganzes Ensemble
zusammenwirkender Klassen kapselt. Oder einen opaken Zeiger auf deine
Interna, die du einer 'Fliegengewicht'-Klasse ohne eigene Daten jedesmal
als Parameter mitgibst. Am Ende ist das Prinzip stets dasselbe: die
Implementierungsklasse wird im externen Header nur deklariert und taucht
in der Definition der benutzersichtbaren Klasse(n) nur als Ziel eines
Zeigers auf. Die Definition für interne Verwendung steht in der
Implementierungsdatei oder einem internen Header.
HTH, Jörg |
|
| Back to top |
|
 |
helmut.weil@t-online.de Guest
|
Posted: Thu Dec 14, 2006 1:59 pm Post subject: Re: Interna der Klasse in Header-Datei vor Benutzer verberge |
|
|
Hallo,
thanks to all.
Eure Antworten haben mir geholfen. Ich dachte schon, es gäbe ne simple
Lösung und ich sähe vor lauter Bäumen den Wald nicht ;-)
Helmut |
|
| Back to top |
|
 |
Hubert Schmid Guest
|
Posted: Thu Dec 14, 2006 2:33 pm Post subject: Re: Interna der Klasse in Header-Datei vor Benutzer verberge |
|
|
"helmut.weil@t-online.de" <helmut.weil@t-online.de> writes:
| Quote: | Wie kann ich die Schnittstelle einer Klasse in einer Header-Datei
veröffentlichen, und trotzdem die Interna Klasse vor dem Benutzer
verbergen:
|
Wenn die Klasse ein Verhalten kapselt, dann verwende ich häufig eine
Basisklasse mit rein virtuellen Funktionen als Schnittstelle. Von
dieser Unterklasse gibt es dann eine oder auch mehrere konkrete
Implementierungen. Diese werden nur in den Implementierungsdateien
deklariert. Das sieht dann ungefähr so aus (alternativ auch mit
getrennter interner und externer Schnittstelle):
// header
struct foo
{
virtual ~foo();
virtual void offen(int param) = 0;
};
std::auto_ptr<foo> create_foo();
// implementierung
foo::~foo() { }
struct foo_impl : foo
{
int a;
void geheim(int param);
virtual void offen(int param);
};
std::auto_ptr<foo> create_foo()
{
return std::auto_ptr<foo>(new foo_impl());
}
Einer der wichtigsten Vorteile gegenüber dem PIMPL-Idiom ist, dass man
auch einfach weitere Implementierungen schreiben kann, beispielsweise
eine Mock-Implementierung zum Testen, ein Decorator oder eine
Proxy-Implementierung.
--
Hubert Schmid - http://www.z42.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
|
|