Überladen

Warum Überladen?

In C wird jedem Identifier (also dem Funktionsnamen) genau eine Funktion zugeordnet. In C++ wird die Signatur zusätzlich zur Identifikation der Funktion verwendet. In Klartext bedeutet das, dass man in C für jede Funktion einen neuen Namen finden muss:

void PrintInteger( int i )
{
  printf( "Integer: %d\n", i );
}
 
void PrintDouble( double d )
{
  printf( "Double: %f\n", d );
}

Wie im Beispiel möchte man allerdings oftmals das gleiche machen, nur eben mit unterschiedlichen Datentypen. Der Zweck der beiden Funktionen ist lediglich etwas auszugeben, dennoch schreibt man den Datentyp dazu, damit der Compiler die Funktionen unterscheiden kann.

Funktionen überladen

In C++ können nun die Parameter (nicht der Rückgabeparameter!) zusätzlich zur Unterscheidung hinzugezogen werden. Das führt dazu, dass man sich beim Funktionsnamen auf die eigentlichen Aufgabe konzentrieren kann:

void Print( int i )
{
  printf( "Integer: %d\n", i );
}
 
void Print( double d )
{
  printf( "Double: %f\n", d );
}

Die Funktion Print gilt nun als „überladen“, da man eine (oder mehrere) Funktionen übereinander geladen hat.

Dabei ist man nicht darauf angewiesen, die gleiche Anzahl von Parametern verwendet.

void Print( int i )
{
  printf( "Integer: %d\n", i );
}
 
void Print( int i, int j )
{
  printf( "Integer addiert: %d und %d\n", i + j );
}

Methoden überladen

Wie man Funktionen überladen kann, so kann man auch Methoden überladen:

class MyInteger
{
private:
  int Value;
public:
 
  void Print();
  void Print( int j );
};
 
void MyInteger::Print()
{
  printf( "Integer: %d\n", Value );
}
 
void MyInteger::Print( int j )
{
  printf( "Integer addiert: %d\n", Value + j );
}

Default Parameter

Aufpassen muss man jedoch bei Default-Parametern, dass man keine Funktionen überlädt, die mehrdeutug sind:

class MyInteger
{
private:
  int Value;
public:
  MyInteger( int value ) : Value( value ) {}
 
  void Print();
  void Print( int j = 0 );
};
 
void MyInteger::Print()
{
  printf( "Integer: %d\n", Value );
}
 
void MyInteger::Print( int j )
{
  printf( "Integer addiert: %d\n", Value + j );
}
 
int main()
{
  MyInteger myInt(4);
 
  myInt.Print();
 
  return 0;
}

In diesem Beispiel ist der Aufruf myInt.Print() mehrdeutig, da beide Print-Funktionen gemeint sein könnten. Der Default-Parameter muss in diesem Fall also weg. Grundsätzlich sind Default-Parameter natürlich erlaubt, sofern keine Mehrdeutigkeiten entstehen.