const hinter Funktion



  • Hallo.
    Ich sehe des öfteren ein "const" hinter einer Funktion, z.B.:

    int Foo(int &var) const
    {
     //...
    }
    

    Was bringt dieses const?

    Gruß Speedy_92



  • Es garantiert, dass die Methode das Objekt nicht verändert und somit auch auf konstante Objekte angewandt werden kann.



  • 😕 Tut mir leid... nicht verstanden. Welches Objekt meinst du?



  • Meinst du damit, dass die Methode Foo unbedingt eine Klassenmethode sein muss?



  • Öhm nein, diese Methode garantiert das keine Member geändert werden können. Somit würde dich der Compiler darauf hinweisen wenn du ausversehen versuchst mit dieser Methode Member zu ändern.



  • Alles klar. Vielen Dank.
    Meinst du mit Member nur Klassenvariablen oder auch ganz normale (globale z.B.) Variablen?



  • Speedy_92 schrieb:

    Meinst du damit, dass die Methode Foo unbedingt eine Klassenmethode sein muss?

    doch?

    sonst gäbs ja nichts, was die fkt nicht verändern darf?!

    also das wär ja sinnlos: (es sei denn, du hast das "class x {" weggelassen ^^)

    void Foo () const
    {
    /*...*/
    }
    

    so würde es aber Sinn machen:

    void Bar::Foo () const
    {
    /*...*/
    }
    

    Alle Funktionen, die das Objekt (die Klasse) nicht verändern können, sollten auch als 'const' deklariert werden - bestes Beispiel dafür sind wohl Getter-Fkt...

    bb



  • Alles klar. Jetzt habe ich es verstanden 👍

    Ja, aber so würde es schon Sinn machen:

    void Foo (int blub) const
    {
    /*...*/
    }
    

    *EDIT: Aber irgendwie ja doch nicht 😃 weil bei dieser Methode bräuchte man das const ja gar nicht...



  • Das const bezieht sich auf den "this" Pointer, damit sollte dann auch klar sein dass und warum es bei freien Funktionen/statischen Memberfunktionen kein const an der Stelle geben kann.



  • Speedy_92 schrieb:

    Meinst du mit Member nur Klassenvariablen oder auch ganz normale (globale z.B.) Variablen?

    Alle mit Ausnahme der als mutable deklarierten Klassenvariablen.

    Speedy_92 schrieb:

    Ja, aber so würde es schon Sinn machen: [...]

    Nein, es kann nur für Memberfunktionen von Klassen eingesetzt werden. Wenn du übergebene Variablen nicht verändern willst, übergib sie als Kopie oder konstante Referenz.



  • Jetzt ist es endgültig klar 🙂
    Vielen Dank.



  • unskilled schrieb:

    Alle Funktionen, die das Objekt (die Klasse) nicht verändern können, sollten auch als 'const' deklariert werden - bestes Beispiel dafür sind wohl Getter-Fkt...

    Versuch mal in etwas größeren Code ( schon 20 Funktionen reichen aus ) ein viertel davon als const zu deklarieren - der Compiler macht dich fertig, er saugt dich aus und spuckt wieder aus wie ein Welpe die Zeitung. -Irgendwann wird der Compiler meinen alles müsse nun const sein, und auch auch die funktionen die genau so verwendet werden wie deklariert und definiert finden plötzlich keine übereinstimmung.

    Ich habs zwar nicht wirklich verstanden wieso, aber anscheind macht ein Objekt, der aus const funktion kommt die nächste funktion, wo es als eingabe kommt, auch const.

    K.A. wieso - die Compilerentwickler würden sich schon was dabei gedacht haben, nur hat es mich davon abgebracht irgendwo noch mal bei Funktionen "const" zu schreiben



  • ddd9876 schrieb:

    Versuch mal in etwas größeren Code ( schon 20 Funktionen reichen aus ) ein viertel davon als const zu deklarieren - der Compiler macht dich fertig, er saugt dich aus und spuckt wieder aus wie ein Welpe die Zeitung. -Irgendwann wird der Compiler meinen alles müsse nun const sein, und auch auch die funktionen die genau so verwendet werden wie deklariert und definiert finden plötzlich keine übereinstimmung.

    Ich habs zwar nicht wirklich verstanden wieso, aber anscheind macht ein Objekt, der aus const funktion kommt die nächste funktion, wo es als eingabe kommt, auch const.

    Bei mir sind alle Funktionen, die const sind, auch const und das sind fast immer deutlich mehr als ein Viertel.
    Wahrscheinlich liegt bei dir genau da der Fehler: du hast vergessen, Funktionen, die const sein sollten, als solche zu deklarieren. Eine const-Funktion darf keine non-const-Memberfunktionen aufrufen, müsste eigentlich klar sein.
    Falls sie das bei dir doch tun muss, hast du einen Denkfehler gemacht und deine aktuelle Funktion ist wohl doch nicht ganz so const.



  • ddd9876 schrieb:

    unskilled schrieb:

    Alle Funktionen, die das Objekt (die Klasse) nicht verändern können, sollten auch als 'const' deklariert werden - bestes Beispiel dafür sind wohl Getter-Fkt...

    Versuch mal in etwas größeren Code ( schon 20 Funktionen reichen aus ) ein viertel davon als const zu deklarieren - der Compiler macht dich fertig, er saugt dich aus und spuckt wieder aus wie ein Welpe die Zeitung.

    Grundsätzlich sollte man const-correctness auch komplett umsetzen, und nicht halbherzig. Es hilft bei der Compileroptimierung, es gewährt den Schnittstellenbenutzer gewisse Garantien, und macht allgemein das Leben einfacher.

    ddd9876 schrieb:

    Irgendwann wird der Compiler meinen alles müsse nun const sein, und auch auch die funktionen die genau so verwendet werden wie deklariert und definiert finden plötzlich keine übereinstimmung.

    Nein, der Compiler prüft dann nur ob die Aufrufe innerhalb des const-Kontextes auch passen. Zudem ist const ein Teil der Methodensignatur (z.B. hat der std::vector einen manipulierenden und ein nicht-manipulierenden Indexoperator).

    ddd9876 schrieb:

    Ich habs zwar nicht wirklich verstanden wieso, aber anscheind macht ein Objekt, der aus const funktion kommt die nächste funktion, wo es als eingabe kommt, auch const.

    Logisch: Wenn eine Methode garantiert das keine Änderung an dem Objekt durchgeführt wird, kann dies nur klappen wenn die Aufrufe der Methode selbst auch const sind. Man sollte nicht über Features meckern, ohne sie verstanden zu haben.

    ddd9876 schrieb:

    K.A. wieso - die Compilerentwickler würden sich schon was dabei gedacht haben, nur hat es mich davon abgebracht irgendwo noch mal bei Funktionen "const" zu schreiben

    Schau dir mal den Link oben an, lese ihn dir durch, und vielleicht wirst auch du dann bekehrt. Ansonsten hoffe ich, das du niemals in einem Projekt mit mehreren Beteiligten arbeitest...



  • ddd9876 schrieb:

    ...
    Versuch mal in etwas größeren Code ( schon 20 Funktionen reichen aus ) ein viertel davon als const zu deklarieren - der Compiler macht dich fertig, ...

    Versuch mal, einen etwas größeren nicht-const-klaren Code (nach einem Jahr mit Wartungsmaßnahmen durch Andere) zu re-designen: Du wirst im Gestrüpp ungeklärter Abhängigkeiten wahnsinnig werden und mit Schaum vor dem Mund alles wegschmeissen, neu schreiben und (z.B. aufgrund zu eng geplanten Budgets) eine noch grottigere Version auf den Markt schmeissen. 😉
    Mal ehrlich: Wenn Dir die Invarianten klar sind, ist es auch kein Problem, sie per const zu deklarieren - und der Compiler schmeisst einem dabei auch keine Steine in den Weg.
    Wenn sie dir nicht klar sind, wirst Du schlechten Code produzieren - das hat nichtmal was mit const zu tun.

    Gruß,

    Simon2.



  • asc schrieb:

    ...lese ihn ...

    -> "lies" ... 😉
    Ansonsten: 100%ig meine Meinung.

    Ich habe auch einen Kollegen, der mir "immer Du mit Deinem const-Zeug" vorwarf.
    Jetzt überarbeiten wir gerade den Code eines anderen Kollegen, der es damit auch nicht so hatte (und - aus anderen Gründen 😉 - nicht mehr in der Firma ist).
    Jetzt wird sein Protest deutlich leiser, wenn er auch immer noch nicht ganz überzeugt ist. Er hängt noch im "muss das eigentlich alles so kompliziert sein?" und wird auf meine Hinweise "Mit einem const hier und einem da wäre das absolut einfach" ein wenig mislaunig .... 😉
    Aber ich denke schon, dass er die Vorteile sieht.

    BTW: Eine der schlimmsten C-Traditionen finde ich ja, dass

    char* c = "Hallo";
    

    erlaubt ist.

    Gruß,

    Simon2.



  • Holla!

    Gibt es eine Möglichkeit wie ich aus einer als const deklarierten Funktion den this pointer als return Wert verwenden kann? (Dadurch verändere ich ja das Objekt noch nicht?!)

    Danke & Gruss



  • fred001 schrieb:

    Holla!

    Gibt es eine Möglichkeit wie ich aus einer als const deklarierten Funktion den this pointer als return Wert verwenden kann? (Dadurch verändere ich ja das Objekt noch nicht?!)

    Danke & Gruss

    Manchmal postet man doch etwas zu schnell...

    const_cast<>() ist die Lösung.

    Objekt* myfunction() const
    {
      *Berechne etwas*
      if(blabla) return const_cast<Objekt*>(this);
    }
    

    Trotzdem: Ist das hässlich so?
    Ich meine nicht, da die logische Idee hinter const (dass eben das Objekt nicht verändert wird) gewahrt bleibt. Meines Erachtens kommt man hier nur mit der Implementation von "const" in einen Konflikt, entsprechend würde ich dies so akzeptieren. Was meint ihr?



  • Ist das hässlich so?

    Ja.

    #include <iostream>
    
    class Foo
    {
    public:
    
       Foo()
       {}
    
       const Foo* bar() const
       {
          std::cout << "Foo::bar() const" << std::endl;
          return this;
       }
    
       Foo* bar()
       {
          std::cout << "Foo::bar()" << std::endl;
          return this;
       }
    };
    
    int main()
    {
       Foo foo;
       Foo* f = foo.bar();
    
       const Foo cfoo;
       const Foo* cf = cfoo.bar();
    }
    


  • wx++ schrieb:

    Ist das hässlich so?

    Ja.

    Begründung? Was willst du mit deinem Code aussagen? Der ist unnütz.

    Es geht um eine Funktion, die nichts am Objekt ändert, aber keinen konstanten Pointer zurückgeben soll, da danach mit diesem gearbeitet wird.



  • fred001 schrieb:

    wx++ schrieb:

    Ist das hässlich so?

    Ja.

    Begründung? Was willst du mit deinem Code aussagen? Der ist unnütz.

    Es geht um eine Funktion, die nichts am Objekt ändert, aber keinen konstanten Pointer zurückgeben soll, da danach mit diesem gearbeitet wird.

    Eine const -Funktion gerantiert nicht nur, dass die Funktion selbst am Objekt nichts ändert, sondern auch, dass aufgrund des Aufrufs an anderer Stelle keine Änderungen erfolgen dürfen.
    Deshalb darf man aus einer const -Funktion auch nur andere const -Funktionen aufrufen. Bei non-const -Funktionen gibt es einen Fehler.
    Dein Kram unterläuft diesen Mechanismus und führt im Falle eines tatsächlich als const deklarierten Objekts zu undefiniertem Verhalten.

    wx++ macht es richtig.


Anmelden zum Antworten