const vor dem Parameter vs const nach dem Funktionsnamen c ++

86

Was ist der Unterschied zwischen so etwas?

friend Circle copy(const Circle &);

und so ähnlich

friend Circle copy(Circle&) const;

Ich kenne const, nachdem die Funktion verwendet wurde, um dem Compiler mitzuteilen, dass diese Funktion nicht versucht, das Objekt zu ändern, für das sie aufgerufen wird. Was ist mit dem anderen?

jazzybazz
quelle
6
dass Sie den Parameter nicht ändern, ist der andere
Chad

Antworten:

194

Die erste Form bedeutet, dass das (Status des) CircleObjekts, das an die Referenz gebunden ist, die der Parameter der copy()Funktion ist, copy()durch diese Referenz nicht geändert wird . Die Referenz ist eine Referenz auf const, daher ist es nicht möglich, Mitgliedsfunktionen von Circleüber diese Referenz aufzurufen , die selbst nicht als qualifiziert sind const.

Die zweite Form ist dagegen illegal: Nur Mitgliedsfunktionen können qualifiziert werden const(während das, was Sie dort deklarieren, eine globale friendFunktion ist).

Wenn consteine Mitgliedsfunktion qualifiziert wird, bezieht sich die Qualifikation auf das implizite thisArgument. Mit anderen Worten, diese Funktion darf den Status des Objekts, auf das sie aufgerufen wird (das Objekt, auf das der implizite thisZeiger zeigt), nicht ändern - mit Ausnahme von mutableObjekten, aber das ist eine andere Geschichte.

Um es mit Code zu sagen:

struct X
{
    void foo() const // <== The implicit "this" pointer is const-qualified!
    {
        _x = 42; // ERROR! The "this" pointer is implicitly const
        _y = 42; // OK (_y is mutable)
    }

    void bar(X& obj) const // <== The implicit "this" pointer is const-qualified!
    {
        obj._x = 42; // OK! obj is a reference to non-const
        _x = 42; // ERROR! The "this" pointer is implicitly const
    }

    void bar(X const& obj) // <== The implicit "this" pointer is NOT const-qualified!
    {
        obj._x = 42; // ERROR! obj is a reference to const
        obj._y = 42; // OK! obj is a reference to const, but _y is mutable
        _x = 42; // OK! The "this" pointer is implicitly non-const
    }

    int _x;
    mutable int _y;
};
Andy Prowl
quelle
11
Helluva Antwort! Vielen Dank!
SexyBeast
1
Also, für den zweiten Fall, wenn ich ein constObjekt objder Klasse habe Xund bar()wie ich rufe obj.bar(obj), was soll passieren und warum? Sollte nicht obj._x = 42scheitern, da im Anrufer objdeklariert const?
SexyBeast
1
Was ist mit dem Fall, in dem Sie die letztere Balkenfunktion ( void bar(X const& obj) {...}) so aussehen lassen? void bar(const X& obj) {...}, ändert das Verschieben des constSchlüsselworts an diesen Speicherort etwas? Wenn ja, können Sie dieses Beispiel bitte auch hinzufügen?
Gabriel Staples
1
@ GabrielStaples Sie sind die gleichen; constgilt für das, was links ist, oder für das, was rechts ist, falls links nichts ist. In Ihrem Fall werden Sie sehen, dass für beide Versionen constangewendet wird X.
Andreas Flöjt
69

C ++ - Klassenmethoden haben einen impliziten thisParameter, der vor allen expliziten steht. Also eine Funktion, die in einer Klasse wie dieser deklariert ist:

class C {
  void f(int x);

Sie können sich vorstellen, dass es wirklich so aussieht:

  void f(C* this, int x);

Wenn Sie es jetzt so deklarieren:

  void f(int x) const;

Es ist, als hättest du das geschrieben:

  void f(const C* this, int x);

Das heißt, das Trailing constmacht den thisParameter const, was bedeutet, dass Sie die Methode für const-Objekte des Klassentyps aufrufen können und dass die Methode das Objekt, für das sie aufgerufen wurde, nicht ändern kann (zumindest nicht über die normalen Kanäle).

John Zwinck
quelle
2
Perfekt korrekt, beantwortet jedoch nicht die Frage, die sich nicht auf eine Klassenmethode bezieht, sondern auf eine Freundfunktion.
Mah
5
Ja, ich habe mich entschieden, den friendTeil zu ignorieren, weil ich denke, dass er für die eigentliche Frage des OP irrelevant ist (oder was die eigentliche Frage werden wird, wenn alle Probleme ans Licht kommen). So sei es.
John Zwinck
Ich denke, es ist etwas irreführend zu sagen, "Sie können die Methode für const-Objekte des Klassentyps aufrufen", weil Sie die const-Methode für const-Objekte oder nicht-const-Objekte aufrufen können, während nicht-const-Funktionen nur von nicht-const-Objekten aufgerufen werden können. Ansonsten ist dies meine Lieblingsantwort
csguy
8
Circle copy(Circle&) const;

macht die Funktion constselbst. Dies kann nur für Elementfunktionen einer Klasse / Struktur verwendet werden.

Ein Mitglied funktionsfähig zu machen constbedeutet das

  • Es kann keine Nicht-Const-Member-Funktionen aufrufen
  • Es können keine Mitgliedsvariablen geändert werden.
  • Es kann von einem constObjekt aufgerufen werden ( constObjekte können nur constFunktionen aufrufen ). Nicht konstante Objekte können auch eine constFunktion aufrufen .
  • Es muss eine Mitgliedsfunktion der Klasse ' Circle ' sein.

Betrachten Sie nun den nächsten:

Circle copy(const Circle &);

Dies bedeutet, dass der übergebene Parameter nicht innerhalb der Funktion geändert werden kann. Es kann eine Mitgliedsfunktion der Klasse sein oder nicht.

HINWEIS: Es ist möglich, eine Funktion so zu überladen, dass eine constund eine nicht konstante Version derselben Funktion vorhanden ist.

Waqar
quelle
7

Lasst uns alle Verwirrung im Zusammenhang mit klären const


constkam von konstantem Mittelwert etwas ist nicht veränderbar aber lesbar.

  1. Wenn wir unsere Variable mit einem constSchlüsselwort qualifizieren, können wir sie später nicht mehr ändern.
    zB muss die Variable const beim Deklarieren initialisiert werden.
    constint var =25;
    var =50; // gives error

  2. wenn wir unsere Zeigervariable qualifizieren mit nach dann wir können nicht Zeiger selbst ändern , aber Inhalt des Zeigers ist veränderbar . zB // aberconst *

    int *const ptr = new int;
    ptr = new int; //gives error

    *ptr=5445; //allowed

  3. wenn wir unsere Zeigervariable qualifizieren mit , bevor dann wir können Zeiger selbst ändern , aber Inhalt des Zeigers ist nicht veränderbar . zB // aberconst *

    intconst* ptr = new int(85);
    //or
    constint * ptr = new int(85);
    ptr = new int; // allowed

    *ptr=5445; // gives error

  4. Zeiger und Inhalt beide konstant,
    z
    intconst*constptr = new int(85);
    //or
    constint *constptr = new int(85);
    ptr = new int; // not allowed
    *ptr=5445; // not allowed


  1. Circle copy(const Circle &);
    Hier bedeutet const Circle, dass der Wert von Circle nur lesbar ist. Wenn wir versuchen, den Wert von Circle innerhalb der Funktion zu ändern, wird ein Fehler ausgegeben.
  2. friend Circle copy(Circle&) const;
    Diese Art von Funktion gilt nicht für Nicht-Mitgliedsvariablen. Sie wird für Klassen oder Strukturen verwendet. Hier ist die gesamte Funktion mit dem Schlüsselwort const qualifiziert, was bedeutet, dass wir die Objektmitgliedsvariable nicht ändern können . z.B
    class A{ public :
              int  var;
              void fun1()
                    { var = 50; // allowed
                    } 
              void fun2()const
                       { var=50; //not allowed
                       }
           }; 
Ramesh Choudhary
quelle
4

Einer bezieht sich auf den Parameter, der andere auf die Funktion.

Circle copy(const Circle &);

Dies bedeutet, dass der übergebene Parameter innerhalb der Funktion nicht geändert werden kann

Circle copy(Circle&) const;

Die constqualifizierte Funktion wird für Elementfunktionen verwendet und bedeutet, dass Sie die Datenelemente des Objekts selbst nicht ändern können. Das Beispiel, das Sie gepostet haben, war unsinnig.

Lesen Sie von rechts nach links

Wenn wir die erste Funktion umschreiben als Circle copy(Circle const&);, was dasselbe bedeutet, wird klar, dass das Lesen von rechts nach links nützlich wird. copyist eine Funktion, die eine constReferenz auf ein CircleObjekt nimmt und ein CircleObjekt als Referenz zurückgibt .

Alex Chamberlain
quelle
0

friend Circle copy(const Circle &);// bezieht sich auf den konstanten Parameter der Funktion. Der vom Parameter gespeicherte Wert kann nicht geändert werden.

Sie müssen einen Freund in Ihrem Beispiel entfernen. Circle copy (Circle &) const; // kann diesen Poniterwert, der als Konstantenelementfunktion bezeichnet wird, nicht ändern

Shivakumar
quelle
-1
friend Circle copy(const Circle &);

Der Wert des Parameters wird während der Funktionsaufrufe nicht geändert.

friend Circle copy(const Circle &)const ; 

Die Funktion ist ein Accessor, der keinen Wert von Klassenmitgliedern ändert. Im Allgemeinen gibt es verschiedene Arten von Funktionen: Accessoren und Mutatoren. Accessor: Untersucht den Status seines Objekts, ändert ihn jedoch nicht.

Sam
quelle