Wurde bisher immer behauptet, dass der Name einer Funktion oder Memberfunktion eindeutig sein muss, so werden wir diese Einschränkung nun etwas aufweichen. Unter C++ ist es möglich, unter gewissen Randbedingungen mehrere Funktionen oder auch Memberfunktionen mit gleichem Namen zu definieren. Diese 'Mehrfach-Definitionen' werden auch als Überladen bezeichnet.
|
|
Wenn nun aber mehrere Memberfunktionen den gleichen Namen haben, so müssen sich diese irgendwie unterscheiden, damit beim Aufruf der Memberfunktion ersichtlich wird, welche Memberfunktion gemeint ist. Dazu müssen sich die Signaturen der Memberfunktionen in mindestens einem der folgenden Punkte unterscheiden:
1. Die Memberfunktionen besitzen eine unterschiedliche Anzahl von Parametern.
class Window
{
void SetData();
void SetData(char*);
void SetData(char*, int);
....
};
|
2. Die Datentypen der Parameter sind unterschiedlich.
class Window
{
void SetData(char*);
void SetData(ifstream&);
....
};
|
Obacht geben müssen Sie, wenn Sie auf const correctness Wert legen. Der const-Qualifizierer bei Parametern wird beim Überladen nicht ausgewertet.
class Window
{
void SetData(int);
void SetData(const int); // FEHLER!
....
};
|
Sehen wir uns noch ein Beispiel für das Überladen von Funktionen an. Die beiden Funktionen Swap(...) dienen zum Vertauschen von zwei Werten. Die erste Funktion vertauscht zwei short-Werte und die zweite Funktion zwei double-Werte.
// Vertauscht zwei short-Werte void Swap (short& v1, short& v2); // Vertauscht zwei double-Werte void Swap (double& v1, double& v2); |
|
short sVar; double dVar; ... Swap (sVar, dVar); |
|
|
Sehen wir uns noch einige weitere Beispiele zum Überladen von Memberfunktionen an:
class Window
{
....
public:
// Ausgangs-Memberfunktion
void SetData(char*);
// Fall 1
int SetData(char*);
// Fall 2
void SetData(char*, int nP=1);
// Fall 3
void SetData(char*, char*, int nP=1);
};
|
1. Fall:
Nicht zulässig, da sich die Memberfunktion nur im Returntyp von der
Ausgangs-Memberfunktion unterscheidet.
2. Fall:
Auch dieser Fall ist unzulässig, da beim Aufruf der Memberfunktion der
zweite Parameter (Default-Parameter) entfallen kann und sich der Aufruf
damit eventuell nicht von der Ausgangs-Memberfunktion unterscheidet.
3. Falls:
Zulässiger Fall, da die Memberfunktion mit mindestens zwei Parametern
aufgerufen werden muss.
|
|
1. Rechteck: |
// Beispiel zu überladenen Memberfunktionen // 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. Memberfunktion zum Setzen der Recheck Daten mit 4 Parametern void SetData(short x, short y, short w, short h); // 2. Memberfunktion zum Kopieren eines Rechtecks void SetData(const Rect& source); // Ausgabe der Rechteck Daten void PrintRect() const; }; // Definition der Memberfunktionen // 1. Memberfunktion SetData() der Klasse Rect // Erhält als Parameter die Rechteck-Daten als 4 short Werte void Rect::SetData(short x, short y, short w, short h) { xPos = x; yPos = y; width = w; height = h; } // 2. Memberfunktion SetData() der Klasse Rect void Rect::SetData(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() { // 2 Rechteck Objekte definieren Rect firstRect; Rect secondRect; // Daten der Rechteck Objekte setzen firstRect.SetData(10,20,100,200); secondRect.SetData(11,22,110,220); // Rechteckdaten ausgeben cout << "1. Rechteck:\n"; firstRect.PrintRect(); cout << "2. Rechteck:\n"; secondRect.PrintRect(); // Zweites Rechteck Objekt gleich erstem Objekt setzen secondRect.SetData(firstRect); // Daten des zweiten Objekts ausgeben cout << "2. Rechteck gleich 1. Rechteck gesetzt:\n"; secondRect.PrintRect(); } |
In dieser und den folgenden Übungen soll ein Klasse CString zur Verarbeitung von Strings entwickelt werden. Diese CString-Klasse besitzt zum Schluss einen Teil der Funktionalität, wie sie auch die in der C++ Bibliothek enthaltene string-Klasse besitzt. Sie bauen in den Übungen diese Klasse quasi teilweise nach.
Der Speicherplatz für den in der Klasse abzulegenden String soll dynamisch als char-Feld angelegt werden. Außerdem soll die Klasse ein statisches Datum besitzen, welches die aktuelle Anzahl der String-Objekte enthält.
In dieser Übung sind außer dem notwendigen Standard-Konstruktor und Destruktor folgende Memberfunktionen zu schreiben:
In main() sind zunächst zwei CString-Objekte zu definieren. Das erste CString-Objekt ist mit dem C-String "Es waren " zu belegen und das zweite CString-Objekt bleibt noch leer. Beide CString-Objekte sind zur Kontrolle auszugeben.
Anschließend ist dem ersten CString-Objekt der C-String "zwei Ameisen" und dem zweiten CString-Objekt der C-String "die wollten nach Amerika reisen" hinzuzufügen. Beide CString-Objekte sind zur Kontrolle erneut auszugeben.
Zum Schluss ist noch ein drittes CString-Objekt zu definieren, welches zuerst mit dem erste CString-Objekt belegt wird. Anschließend ist diese String-Objekt der C-String "\n" hinzuzufügen und dann noch das zweite CString-Objekt. Geben Sie dieses dritte CString-Objekt ebenfalls aus.
|
|
|
|
|
Ausgangs-Strings Nach AddString(...) Neuer String |