| Axel Rogat |
| Objektorientiertes Programmieren mit C++ und JAVA |
|   |
13.8: Überladen von new
| Kapitel 13 |
14: Stream-Klassen 
|
|   |
|   | 13.9 Schnittstellen |   |
|   |
Beim Entwurf einer Klasse nicht für eigene Zwecke, sondern zur Verwendung
durch andere Benutzer, sind einige Überlegungen zu berücksichtigen, um
den Umgang mit der Klasse so einfach und sicher wie möglich zu gestalten.
Es ist im höchsten Maße gefährlich, von der üblichen
Semantik einiger Funktionen, insbesondere Operatoren, abzuweichen. Es gibt
einige Funktionen, auf deren Funktionalität sich der Benutzer einer Klasse
verlassen können muß.
Diese Funktionen werden oft reguläre Funktionen genannt. Sie sind
hier für eine Klasse T aufgeführt:
Der Copy-Konstruktor
sollte immer ein Objekt erzeugen, das
sich exakt so verhält wie seine Vorlage. Außer in wenigen sinnvollen
(und dann gut dokumentierten) Fällen sollte es danach auch keinerlei
implizite Verbindung (z.B. durch Verpointerung) zum ursprünglichen Objekt
besitzen.
Der Destruktor sollte die Ressourcen freigeben, die im Lauf der
Lebenszeit des Objekts belegt wurden.
Der primäre Zuweisungsoperator
(also der, der auf der rechten Seite
ein Objekt der gleichen Klasse hat: const T& oder
T),
sollte das Objekt auf der linken Seite so modifizieren, daß es danach exakt
die Werte des Objekts auf der rechten Seite hat. Die Semantik zum Einbau
solcher Zuweisungen in größere Ausdrücke sollte beibehalten
werden, d.h. eine Referenz auf das linke Objekt sollte zurückgegeben
werden.
Die Vergleichsoperatoren
== und != sollten den Rückgabetyp
bool haben. == sollte genau dann
true liefern, wenn die beiden Operanden alles exakt gleiche
Werte besitzen. != sollte die Negation des anderen Operators
sein und, wenn sinnvoll, zur Sicherheit auch unter seiner Zuhilfenahme
implementiert werden.
Auf die explizite Implementation dieser Funktionen kann nur verzichtet
werden, wenn die vom Compiler automatisch bereitgestellten Ersatzfunktionen
die gleiche Semantik haben würden. Fast immer kann man
sie nur dann weglassen, wenn kein dynamischer Speicher beteiligt ist.
Bei Klassen mit arithmetischen Eigenschaften sollte die Semantik für
kombinierte Zuweisungsoperatoren wie += auch immer die sein, als
würde zunächst mit dem Operator + ein temporäres
Objekt erzeugt und dann mit = zugewiesen.
Einige Funktionen sollten in einer allgemein verwendbaren Klasse auf jeden
Fall definiert werden. Ihr Weglassen kann zu unerwünschten Effekten oder
zu eingeschränkter Benutzbarkeit führen.
Beispielsweise kann man nur Arrays von Objekten einer Klasse anlegen,
wenn ein Default-Konstruktor (ohne Parameter) definiert ist, entweder
explizit oder -- falls sinnvoll -- durch die Abwesenheit jedes Konstruktors.
Viele sinnvolle Funktionen wie Tauschen, Suchen, etc. werden durch
Templates implementiert, so daß sie für beliebige Klassen
durchführbar sind. Für das Tauschen ist aber der primäre
Zuweisungsoperator notwendige Voraussetzung, für das Suchen der
Vergleichsoperator ==.
Eine Klasse, die die folgenden wichtigen Funktionen (explizit oder
implizit) implentiert, wird oft " nice class" genannt:
Es ist leider nicht sinnvoll, eine minimale Sammlung von Operationen mit
ihren Semantiken vorzuschreiben, die einer vernünftige Klasse auf jeden
Fall bereitstellen sollte. Für fast jede Funktion läßt sich eine
Klasse finden, bei der die geforderte Standard-Implementation unvernünftig
wäre.
13.9.1 Reguläre Funktionen
13.9.2 Nice Classes
¤ Default-Konstruktor
  T::T();
¤ Copy-Konstruktor
  T::(const T&);
¤ Zuweisungsoperator
  T& T::operator = (const T&);
¤ Vergleichsoperator
  bool T::operator == (const T&);
¤ Destruktor
  T::~T();
|   |
13.8: Überladen von new
| Startseite |
14: Stream-Klassen 
|
|   |