const prima del parametro vs const dopo il nome della funzione c ++


90

Qual è la differenza tra qualcosa di simile

friend Circle copy(const Circle &);

e qualcosa del genere

friend Circle copy(Circle&) const;

Conosco const dopo che la funzione è stata utilizzata per dire al compilatore che questa funzione non tenterà di cambiare l'oggetto su cui è chiamata, e l'altra?


6
che non cambierai il parametro è l'altro
Chad

Risposte:


199

La prima forma significa che lo (stato Circledell'oggetto ) legato al riferimento che è il parametro della copy()funzione non sarà alterato da copy()quel riferimento. Il riferimento è un riferimento a const, quindi non sarà possibile invocare funzioni membro di Circletramite quel riferimento che non sono a loro volta qualificate come const.

La seconda forma, d'altra parte, è illegale: solo le funzioni membro possono essere constqualificate (mentre quello che stai dichiarando è una friendfunzione globale ).

Quando constqualifica una funzione membro, la qualifica fa riferimento thisall'argomento implicito . In altre parole, a quella funzione non sarà permesso di alterare lo stato dell'oggetto su cui è invocata (l'oggetto puntato dal thispuntatore implicito ) - ad eccezione degli mutableoggetti, ma questa è un'altra storia.

Per dirlo con il codice:

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;
};

12
Risposta Helluva! Grazie!
SexyBeast

1
Quindi, per il secondo caso, se ho un constoggetto objdi classe Xe chiamo bar()like obj.bar(obj), cosa dovrebbe succedere e perché? Non dovrebbe obj._x = 42fallire, poiché objè dichiarato constnel chiamante?
SexyBeast

1
E il caso in cui si fa in modo che quest'ultima funzione bar ( void bar(X const& obj) {...}) assomigli a questa? void bar(const X& obj) {...}, spostare la constparola chiave in questa posizione cambia qualcosa? Se è così, puoi aggiungere anche questo esempio per favore?
Gabriel Staples il

1
@GabrielStaples Sono gli stessi; constsi applica a ciò che è alla sua sinistra oa ciò che è alla sua destra nel caso in cui non ci sia nulla a sinistra. Nel tuo caso vedrai che per entrambe le versioni constè applicato a X.
Andreas Flöjt

70

I metodi della classe C ++ hanno un thisparametro implicito che viene prima di tutti quelli espliciti. Quindi una funzione dichiarata all'interno di una classe come questa:

class C {
  void f(int x);

Puoi immaginare che sia davvero così:

  void f(C* this, int x);

Ora, se lo dichiari in questo modo:

  void f(int x) const;

È come se avessi scritto questo:

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

Cioè, il trailing constrende il thisparametro const, il che significa che puoi invocare il metodo su oggetti const del tipo di classe e che il metodo non può modificare l'oggetto su cui è stato invocato (almeno, non tramite i canali normali).


2
Perfettamente corretto tuttavia non risponde alla domanda, che in realtà non si riferisce a un metodo di classe ma piuttosto a una funzione amico.
mah

5
Sì, ho scelto di ignorare la friendparte perché penso che in realtà sia irrilevante per la vera domanda dell'OP (o quale sarà la vera domanda una volta che tutti i problemi verranno alla luce). Così sia.
John Zwinck

Penso che sia leggermente fuorviante dire "puoi invocare il metodo su oggetti const di tipo classe" perché puoi invocare il metodo const su oggetti const o oggetti non const, mentre le funzioni non const possono essere chiamate solo da oggetti non const. altrimenti questa è la mia risposta preferita
csguy

8
Circle copy(Circle&) const;

fa la funzione conststessa. Può essere utilizzato solo per le funzioni membro di una classe / struttura.

Fare in modo che un membro funzioni constsignifica questo

  • non può chiamare alcuna funzione membro non const
  • non può modificare alcuna variabile membro.
  • può essere chiamato da un constoggetto (gli constoggetti possono chiamare solo constfunzioni). Gli oggetti non const possono anche chiamare una constfunzione.
  • Essa deve essere funzione membro della classe ' Circle '.

Ora considera il prossimo:

Circle copy(const Circle &);

mentre questo significa che il parametro passato non può essere modificato all'interno della funzione. Può o non può essere una funzione membro della classe.

NOTA: è possibile sovraccaricare una funzione in modo tale da avere una versione conste non const della stessa funzione.


8

CHIARIAMO TUTTA LA CONFUSIONE RELATIVA A const


constderiva da costante significa che qualcosa non è modificabile ma leggibile.

  1. se qualifichiamo la nostra variabile con la constparola chiave, non possiamo cambiarla in seguito.
    ad esempio, la variabile const deve essere inizializzata quando viene dichiarata.
    constint var =25;
    var =50; // gives error

  2. se qualifichiamo la nostra variabile puntatore con after, non possiamo cambiare il puntatore stesso ma il contenuto del puntatore è modificabile . ad es. // maconst *

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

    *ptr=5445; //allowed

  3. se qualifichiamo la nostra variabile puntatore con prima , possiamo cambiare il puntatore stesso ma il contenuto del puntatore non è modificabile . ad es. // maconst *

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

    *ptr=5445; // gives error

  4. puntatore e contenuto entrambi costanti
    es
    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 &);
    qui const Circle significa che il valore di Circle è solo leggibile, se proviamo a cambiare il valore di Circle all'interno della funzione allora dà errore.
  2. friend Circle copy(Circle&) const;
    Questo tipo di funzione non è per la variabile non membro. Viene utilizzato per la classe o la struttura. Qui l'intera funzione è qualificata con la parola chiave const significa che non possiamo cambiare la variabile membro dell'oggetto . per esempio
    class A{ public :
              int  var;
              void fun1()
                    { var = 50; // allowed
                    } 
              void fun2()const
                       { var=50; //not allowed
                       }
           }; 

4

Uno si riferisce al parametro, l'altro alla funzione.

Circle copy(const Circle &);

Ciò significa che il parametro passato non può essere modificato all'interno della funzione

Circle copy(Circle&) const;

La constfunzione qualificata viene utilizzata per le funzioni membro e significa che non è possibile modificare i membri dati dell'oggetto stesso. L'esempio che hai postato non aveva senso.

Leggi da destra a sinistra

Se riscriviamo la prima funzione come Circle copy(Circle const&);, che significa la stessa cosa, diventa chiaro che la lettura da destra a sinistra diventa utile. copyè una funzione che prende un constriferimento a un Circleoggetto e restituisce un Circleoggetto per riferimento.


0

friend Circle copy(const Circle &);// si riferisce al parametro costante della funzione. non posso cambiare il valore memorizzato dal parametro.

Devi rimuovere un amico nel tuo esempio Circle copy (Circle &) const; // non è possibile modificare questo valore poniter denominato come funzione membro costante


0
friend Circle copy(const Circle &);

Il valore del parametro non verrà modificato durante le chiamate di funzione.

friend Circle copy(const Circle &)const ; 

La funzione è una funzione di accesso che non modifica alcun valore dei membri della classe. In generale, ci sono tipi di funzioni: accessors e mutator. Accessor: esamina ma non cambia lo stato del suo oggetto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.