Const-Methoden

Ist ein Objekt als konstant markiert, dann darf man natürlich auch keine Methoden mehr aufrufen, die das Objekt verändern könnten. Nehmen wir unsere Klasse Data erneut und geben ihr Setter und Getter.

class Data
{
  private:
    int Date;
 
  public: 
    int GetDate()
    { 
      return Date;
    }   
    bool SetDate( int date )
    {
      Date = date;
      return true;  // Datum erfolgreich gesetzt
    }
};

Und nun greifen wir mit einem konstanten Objekt darauf zu:

int main( void )
{
  Data data;
  data.SetDate( 1 );
 
  Data const & constData = data;
 
  constData.SetDate( 2 );
  printf( "Datum ist: %d\n", constData.GetDate() );  
 
  return 0;  
}

Wir sehen hier nochmal ganz deutlich, dass es problemlos möglich ist, eine konstante Referenz auf ein variables Objekt zu verwenden. Dennoch lässt sich der Quelltext nicht kompilieren.

method.cpp: In function ‘int main()’:
method.cpp:27: error: passing ‘const Data’ as ‘this’ argument of ‘bool Data::SetDate(int)’ discards qualifiers
method.cpp:28: error: passing ‘const Data’ as ‘this’ argument of ‘int Data::GetDate()’ discards qualifiers

(Hinweise zur Fehlermeldung)

Auf ein Const-Objekt darf nicht schreibend zugegriffen werden, also dürfen keine normalen Methoden verwendet werden, da sie ja eventuell schreibend zugreifen könnten. Methoden, die bei const-Objekten erlaubt sein sollen, müssen entsprechend gekennzeichnet werden. Dafür ändern wir die Signatur der Methoden in dem wir ein const anhängen:

class Data
{
  private:
    int Date;
 
  public: 
    int GetDate() const
    { 
      return Date;
    }   
    bool SetDate( int date ) const
    {
      Date = date;
      return true;  // Datum erfolgreich gesetzt
    }
};

Ich erlaube nun den Methoden GetDate() und SetDate( int ), dass man sie von Const-Objekten aus rufen darf. Doch damit ist der Compiler nicht zufrieden:

method.cpp: In member function ‘bool Data::SetDate(int) const’:
method.cpp:15: error: assignment of data-member ‘Data::Date’ in read-only structure

Die Zuweisung in SetDate ist in einer Const-Methode nicht erlaubt, was zeigt, dass ich hier einen Fehler im Design habe: SetDate und const passt einfach nicht zusammen. So ist es richtig: Const-Objekte dürfen GetDate() verwenden und SetDate() darf nur von variablen Objekten gerufen werden.

class Data
{
  private:
    int Date;
 
  public: 
    int GetDate() const
    { 
      return Date;
    }   
    bool SetDate( int date )
    {
      Date = date;
      return true;  // Datum erfolgreich gesetzt
    }
};

Nun fügen wir aber nur zu Anschauungszwecken noch eine Überladung hinzu:

class Data
{
  private:
    int Date;
 
  public: 
    int GetDate() const
    { 
      return Date;
    }   
    bool SetDate( int date )
    {
      Date = date;
      return true;  // Datum erfolgreich gesetzt
    }
    bool SetDate( int date ) const
    {
      printf( "Aufruf von SetDate an konstantem Objekt. Konnte Wert %d nicht annehmen\n", date );
      return false;  // Datum konnte nicht gesetzt werden
    }
};

Das lässt sich nun kompilieren. Der Compiler hat für variable Objekte eine Methode und für konstante Objekte eine andere Methode, die keine Werte verändert. Das Programm liefert nun:

Aufruf von SetDate an konstantem Objekt. Konnte Wert 2 nicht annehmen
Datum ist: 1

Ändere ich den Ausgabe wie folgt:

Data data;
data.SetDate( 1 );
 
Data const & constData = data;
 
constData.SetDate( 2 );
printf( "Datum ist (const): %d\n", constData.GetDate() );  
printf( "Datum ist: %d\n", data.GetDate() ); 

…so erhält man folgende Ausgabe:

Aufruf von SetDate an konstantem Objekt. Konnte Wert 2 nicht annehmen
Datum ist (const): 1
Datum ist: 1

In beiden Fällen wird die const-Methode für GetDate() gerufen, da ein variables Objekt sich jederzeit wie ein konstantes Objekt verhalten kann.