Überladen des Konstruktors
Kopierkonstruktor
Beispiel und Übung
Nachdem Sie in der letzten Lektion etwas über das allgemeine Überladen von Funktionen bzw. Memberfunktionen erfahren haben, sehen wir uns jetzt das Überladen des Konstruktors an.
Hatten unsere Klassen bisher immer nur einen Konstruktor, so ermöglicht das Überladen des Konstruktors, dass ein Objekt einer Klasse auf verschiedene Weisen definiert werden kann. Und auch für das Überladen des Konstruktors gilt: die Konstruktore müssen sich in der Anzahl der Parameter und/oder Datentypen der Parameter unterscheiden. Welcher Konstruktor dann ausgeführt wird, hängt von den Parametern bei der Definition des Objekts ab.
class Window
{
....
public:
Window(); // Standard-ctor
Window(char*, short); // 2. ctor
....
};
int main()
{
Window myWin; // Standard-ctor
Window yourWin("Emil",10); // 2. ctor
....
}
|
Beachten Sie in diesem Zusammenhang auch, dass Sie den Standard-Konstruktor immer benötigen, wenn Sie Objektfelder dynamisch definieren wollen.
|
|
Eine besondere Form des Konstruktors stellt der Kopierkonstruktor (copy-ctor) dar. Er wird immer dann aufgerufen, wenn ein Objekt bei seiner Definition mit einem anderen Objekt der gleichen Klasse initialisiert wird, d.h. das neue Objekt eine Kopie eines bestehenden Objekts ist. Der Kopierkonstruktor hat folgende Syntax:
| CAny::CAny(const CAny& source); |
CAny ist eine beliebige Klasse und der Referenzparameter source eine Referenz auf das zu kopierende Objekt. Nachfolgend ein Beispiel für einen solchen Kopierkonstruktor.
// Klassendefinition class Window { char *pTitle; .... public: Window(); // Standard ctor Window(const Window& source); // copy-ctor .... }; // Definition des Kopierkonstruktors Window::Window(const Window& source) { // Platz für Fenstertitel reservieren pTitle = new char[strlen(source.pTitle)+1]; // Fenstertitel umkopieren strcpy(pTitel,source.pTitle); .... } int main() { // Aufrufe des Standard-ctor Window firstWin; pAnyWin = new Window; // Beispiele für den Aufruf des copy-ctors Window myWin(firstWin); Window yourWin(*pAnyWin); Window *pWin1 = new Window(firstWin); Window *pWin2 = new Window(*pAnyWin); ... ... // Hier dyn. angelegte Window-Objekte wieder löschen! } |
Beachten Sie bitte bei den Zeigerparametern, dass die Zeiger dereferenziert werden!
|
|
Der Kopierkonstruktor ist in der Regel immer dann erforderlich, wenn eine Klasse dynamische Eigenschaften enthält, da meistens nicht einfach die Zeiger auf die dynamische Eigenschaften kopiert werden dürfen (doppelt belegter Speicherplatz!).
|
|
|
|
1. Rechteck: |
// Beispiel zum überladenen Konstruktor // Zuerst Dateien einbinden #include <iostream> using std::cout; using std::endl; // Klassendefinition class Rect { short xPos, yPos; // Position short width, height; // Breite und Höhe public: // 1. Konstruktor Rect(short x, short y, short w, short h); // 2. Konstruktor (Kopierkonstruktor) Rect(const Rect& source); // Ausgabe der Rechteck Daten void PrintRect() const; }; // Definition der Memberfunktionen // 1. Konstruktor // Erhält als Parameter die Rechteck-Daten als 4 short Werte Rect::Rect(short x, short y, short w, short h) { xPos = x; yPos = y; width = w; height = h; } // 2. Konstruktor (Kopierkonstruktor) Rect::Rect(const Rect& source) { xPos = source.xPos; yPos = source.yPos; width = source.width; height = source.height; } // Ausgabe der Rechteck Daten void Rect::PrintRect() const { cout << "Rechteck auf (" << xPos << "," << yPos << ") "; cout << "Grösse: (" << width << "," << height << ")\n"; } // main() Funktion int main() { // Zeiger auf erste Rect Objekt Rect *pFirstRect; // Erstes Rect Objekt erstellen pFirstRect = new Rect(10,20,100,200); // Zweites Rect Objekt erstellen und mit den Eigenschaften // der ersten Rect Objekts initialisieren Rect *pSecondRect = new Rect(*pFirstRect); // Rechteckdaten ausgeben cout << "1. Rechteck:\n"; pFirstRect->PrintRect(); cout << "2. Rechteck:\n"; pSecondRect->PrintRect(); // Beide Objekte wieder löschen delete pFirstRect; delete pSecondRect; } |
Schreiben Sie die in der letzten Übung erstellte Klasse CString nun so um, dass die beiden Memberfunktionen SetString(...) durch entsprechende Konstruktore ersetzt werden. Die Klasse sollte dann folgende Konstruktore enthalten:
Die anderen Memberfunktionen AddString(...) und PrintString(...) können Sie unverändert übernehmen.
Erstellen Sie in main() ein erstes CString-Objekt, das Sie mit dem C-String "Es waren " initialisieren und ein zweites leeres CString-Objekt. Geben Sie beide CString-Objekte aus.
Fügen Sie dann zum ersten CString-Objekt den C-String "zwei Ameisen" und zum zweiten CString-Objekt den C-String "die wollten nach Amerika reisen" hinzu. Geben Sie beide CString-Objekte wieder aus.
Zum Schluss definieren Sie ein drittes CString-Objekt, das Sie mit dem Inhalt des ersten CString-Objekts initialisieren. Diesem neuen CString-Objekt fügen Sie dann den C-String "\n" so wie das zweite CString-Objekt hinzu. Geben Sie auch dieses Objekt wieder aus.
|
Ausgangs-Strings Nach AddString(...) Neuer String |