passing 'const <Klasse>' as 'this' argument of '... function( ... )' discards qualifiers

Das Problem

Folgendes Fehlermeldung spuckte mein GCC 4.1 heute (mal wieder) aus:

<file>: error: passing 'const <Klasse>' as 'this' argument of 'bool function( ... )' discards qualifiers

Inzwischen kenne ich die Meldung ja schon, aber verstanden habe ich sie erst nachdem ich den Fehler korrigiert habe:

Der Fehler

Der Fehler ist wieder einmal sehr einfach: Man hat eine konstante Instanz von „Klasse“ und ruft nun eine Memberfunktion dieser Klasse auf. Memberfunktionen dürfen bekanntlich Variablen innerhalb der Instanz ändern. Da diese Instanz, mit der die Funktion aufgerufen wird, aber als konstant gekennzeichnet ist, darf die Funktion keine Änderungen vornehmen. Das Versprechen, dass nichts verändert wird, muss klar ausgesprochen werden und wird dann vom Compiler überprüft:

class Klasse
{
  public:
    void Function( void ) const;
};

Das Schlüsselwort 'const' hinter der Parameterliste verbietet der Funktion Änderungen innerhalb der eigenen Instanz zu machen. Dieses const gehört zur Signatur der Funktion, die Funktion kann also auch mit einer gleichnamigen Funktion mit gleichen Argumenten überladen werden, die für nicht-konstante Objekte zuständig ist.

class Klasse
{
  private:
    char * String;
  public:
    char       * GetString( void );        // Version für veränderliche Objekte
    char const * GetString( void ) const;  // Version für konstante Objekte
};

Konstant, aber doch veränderlich

Nicht alle Datensätze müssen in einem konstanten Objekt unveränderlich sein. Eine Liste kann zum Beispiel konstant sein, wenn kein Element hinzugefügt oder gelöscht wird. Der Zeiger auf ein aktuelles Element darf sich unter Umständen aber doch verändern. So kann man die Variablen, die den Wert der Instanz nicht verändern als mutable kennzeichnen. Diese Mutable-Variablen dürfen dann auch von Funktionen geändert werden, die als const gekennzeichnet sind:

class List
{
  private:
    Node * First;
    Node * Last;
    mutable Node * Current;
  public:
    inline void SetCurrent( Node & current ) const { Current = &current; }
};

Quelle