mgl. Funktionendeklaration int value() const ??



  • Hi !

    Ich hab ein C++ Buch gelesen. Nun hab ich aber in einem Quellcode folgende Funtkionerdeklaration gelesen:

    int value() const;

    Ich meine, das nicht in meinem Buch gelesen zu haben. Kann mir jemand diese Deklarition erklären ??

    mfg
    tom



  • das bedeutet, das der this pointer der funktion als konstanter zeiger übergeben wird:

    struct x {
      int v;
      void foo () { v = 10; }
      void bar () const {
         v = 10; //funktioniert nicht
      }
    };
    

    damit gibst du unter anderem die zusicherung, dass das objekt nicht verändert werden kann:

    x test;
    test.foo();
    test.bar();
    
    const x test2;
    test2.foo(); //geht nicht: aufruf einer nicht konstanten memberfunktion
    //für ein constantes objekt
    test2.bar(); //funktioniert, weil ja zugesichert ist, das
    //alle elemente von test2 nicht verändert werden 
    //und das dürfen sie ja auch gar nicht, test2 ist ja const
    

    alles klar bis jetzt?
    dann gibt's noch das keyword mutable, was bewirkt, dass eine
    membervariable in einer konstanten funktion doch verändert werden darf.
    (dann spricht man von logischer konstantheit, im gegensatz zu "echter" konstantheit eines objekts):

    struct y {
      mutable int a;
      int b;
      void foo () { a = 10; }
      void bar () const {
         a = 10; // ist in ordnung
         b = 10; //geht nicht
      }
    };
    

    wie gesagt, das liegt daran, dass jeder memberfunktion als verstecktes 1.argument der this-pointer übergeben wird. bei einer const funktion ist der zeiger konstant (const x* const this statt x* const this)
    was noch einen effekt hat, und zwar bei der funktionsüberladung:

    struct z {
      void foo () { cout << "BLUB\n"; }
      void foo () const { cout << "BLOB\n"; }
    };
    
    void bar (cosnt z *x) {
       x->foo (); //ruft z::foo() const auf
    }
    
    void bar (z *x) {
       x->foo (); //ruft z::foo() auf
    }
    
    void fubar (z *x) {
      const_cast<const z*>(x)->foo(); //ruft z::foo() const auf
    }
    

    soo.. das wäre das gröbste.
    ps dasselbe gilt natürlich auch für volatile, wobei ich nicht weiß, inwieweit mutable da mitspielt. ich vermute mal ähnlich (gleich)



  • Eine Funktion mit den Namen value die nix erwartet und ein int zurückgibt.

    Das const am ende bedeutet das die Funktion garantiert keine Daten zu ändern.

    (Welche auch, wird ja nix übergeben 🤡

    Findest Du eigentlich im zusammenhang mit klassen. Du kannst ja ein Objekt z.B. als const & übergeben haben aber eine Memberfunktion aufrufen die das Objekt ändert. Das darf aber nicht sein. Mit dem const am ende garantierst Du das keine Änderungen in diesem Methodenaufruf am Objekt vorgenommen werden und der Compiler lässt den Aufruf zu.

    class test
    {
     int i;
    public:
      test()
      {
        i = 0;
       }
    
      int foo()
      {
        ++i;
        return i;
      }
      int bar() const
      {
        return i;
      }
    
    };
    
    void testfn(const test & t)
    {
       t.foo();			// Err: Methode foo nicht const
       t.bar();
    }
    
    void testfn2(test & t)
    {
       t.foo();
       t.bar();
    }
    
    int main()
    {
      test myTest;
      testfn(myTest);
      testfn2(myTest);
    }
    


  • Vielen Dank für die Erklärung. Jetzt frage ich mich wozu das überhaupt nötig ist, und man es mit dem Schlüsselwort muteable auch noch komplizierter macht.

    Naja, meine Methode "int value() const;" übernimmt ja keine Daten. Sogesehen kann sie auch nichts ändern, bzw keine unkontrollierte Manipulation der Objektdaten durchführen.
    Kann ich den Programmierstil des Programmierers so interpretieren, dass der mit dem const Ausdruck noch einmal verdeutlichen möchte, dass diese Methode keine Daten ändert ?

    mfg
    tom



  • Asker schrieb:

    Naja, meine Methode "int value() const;" übernimmt ja keine Daten.

    Das stimmt nicht. Beispiel:

    class Foo
    {
       int x;
    public:
       Foo(int xx): x(xx) { }
       int value() const { return x; }
    };
    // ...
    
    Foo f(42);
    cout << f.value() << endl;
    

    Eine Memberfunktion wird immer auf ein Objekt aufgerufen, hier ist f das Objekt und value die Funktion. Das "const" sagt, dass f nicht verändert wird. Muss es auch gar nicht, denn value liest nur eine private Membervariable aus.

    Mal ein fehlerhaftes Beispiel:

    // Klassendeklaration wie eben, aber eine Memberfunktion mehr:
    void set_value(int xx) { x = xx; }
    // ...
    const Foo g(42);
    cout << "Wert vorher: " << g.value() << endl;
    g.set_value(23); // Compilerfehler!
    cout << "Wert nachher: " << g.value() << endl;
    

    Der Compiler blockt den Aufruf von set_value auf g ab, weil g konstant deklariert ist, set_value aber nicht. Der Aufruf von g.value() ist nach wie vor erlaubt, da value durch das const verspricht, das Objekt nicht zu verändern.

    mutable braucht man nur in spezialisierten Fällen, und ich würde mich an deiner Steller erstmal nicht damit belasten. Erstmal const aufsaugen.


Anmelden zum Antworten