C++ Kurs

Überladen von Funkionen/Memberfunktionen

Die Themen:

Einführung
Beispiel zum Überladen
Beispiel und Übung

Einführung

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 im Folgenden von Memberfunktionen die Rede ist, so sind damit auch stets Funktionen gemeint.

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);

Beim Aufruf von überladenen Memberfunktionen findet keine automatischen Typkonvertierung von Parametern statt. So würde zum Beispiel der nachfolgende Aufruf der Swap(...) Funktion einen Übersetzungsfehler liefern!

    short sVar;
   double dVar;
   ...
   Swap (sVar, dVar);

Aber Achtung! Besitzen die überladenen Memberfunktionen Default-Parameter, so achten Sie darauf, dass sich die Memberfunktionen untereinander mindestens in einem Parameter vor dem Default-Parameter unterscheiden. Nur dann ist beim Aufruf der Memberfunktion eindeutig welche Memberfunktion ausgeführt werden soll.

Beispiel zum Überladen

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.

Beispiel und Übung

Beispiel:

Im Beispiel wird eine Klasse für ein Objekt definiert, welches ein Rechteck repräsentiert. Das Rechteck besitzt die üblichen Eigenschaften wie Position und Größe. Zum Setzen der Rechteckdaten werden zwei Memberfunktionen SetData(...) definiert. Die erste Memberfunktion erhält die Rechteckdaten als short-Werte übergeben, während die zweite Memberfunktion die Eigenschaften eines als Parameter übergebenen weiteren Rechtecks verwendet, d.h. es wird eine Kopie des übergebenen Rechtecks erstellt. Die Ausgabe der Rechteckdaten erfolgt mithilfe der Memberfunktion PrintRect(...).

In main() werden zwei Rechteck-Objekte definiert, die anschließend mit unterschiedlichen Daten initialisiert werden. Zur Kontrolle werden die Daten der beiden Objekte ausgegeben. Danach werden die Eigenschaften des ersten Objekts dem zweiten Objekt 'zugewiesen' und das zweite Objekt nochmals ausgegeben.

1. Rechteck:
Rechteck auf (10,20)
Grösse: (100,200)
2. Rechteck:
Rechteck auf (11,22)
Grösse: (110,220)
2. Rechteck gleich 1. Rechteck gesetzt:
Rechteck auf (10,20)
Grösse: (100,200)


// 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();

}

Übung:

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:

  • SetString(const char* const) um einen als char-Zeiger übergebenen String abzulegen.
  • SetString(const CString&) um einen als CString-Referenz übergebenen String abzulegen, d.h. es wird eine Kopie des Ausgangs-Strings erstellt.
  • AddString(const char* const) um einen als char-Zeiger übergebenen String an den aktuellen String anzuhängen.
  • AddString(const CString&) um einen als CString-Referenz übergebenen String an den aktuellen String anzuhängen.
  • Print( ) um die aktuelle Anzahl der String-Objekte und den String auszugeben.

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.

Verwenden Sie zum Kopieren eines Strings in das char-Feld die Funktion strcpy(...), zum Anfügen eines Strings an einen bestehenden String die Funktion strcat(...) und für Berechnung der Länge eines C-Strings die Funktion strlen(...). Für eine Beschreibung dieser Funktionen sehen in der Online-Hilfe Ihres Compiler nach.

Um die Übung soll davon ausgegangen werden, dass bei der Übergabe eines char-Zeigers an eine Memberfunktion der Zeiger auf einen gültigen C-String zeigt.

Ausgangs-Strings
1.String: Es waren
2.String:

Nach AddString(...)
1.String: Es waren zwei Ameisen
2.String: die wollten nach Amerika reisen

Neuer String
3.String: Es waren zwei Ameisen
die wollten nach Amerika reisen

Lösung ansehen!