Cosa significa il modificatore const dopo una dichiarazione di metodo - pagina 6

 
Metodi costanti
I metodi costanti si distinguono per il fatto che non cambiano i valori dei loro campi di classe. Guardiamo un esempio chiamato CONSTFU:
// constfu.cpp
// применение константных методов
class aClass
{
private:
    int alpha;
public:
    void nonFunc()    // неконстантный метод
    { 
        alpha = 99;
    }      // корректно
    void conFunc()const   // константный метод
    { 
        alpha = 99;
    }    // ошибка: нельзя изменить значение поля
};

Un normale metodo nonFunc() può cambiare il valore del campo alfa, ma un metodo costante conFunc() no. Se viene fatto un tentativo di cambiare il campo alfa, il compilatore segnalerà un errore.
Per rendere una funzione una costante, la parola chiave const deve essere specificata dopo il prototipo della funzione, ma prima dell'inizio del corpo della funzione. Se la dichiarazione e la definizione della funzione sono separate, il modificatore const deve essere specificato due volte - sia nella dichiarazione della funzione che nella sua definizione. Ha senso rendere questi metodi, che leggono solo dati dal campo della classe, costanti, perché non hanno bisogno di cambiare i valori dei campi dell'oggetto classe.

L'uso di funzioni costanti aiuta il compilatore a rilevare gli errori e dice anche al lettore dell'elenco che la funzione non cambia i valori dei campi dell'oggetto. Le funzioni costanti possono essere usate per creare e usare oggetti costanti, come vedremo più avanti.

Un esempio della classe Distance

Per non includere molte innovazioni in un unico programma, finora non abbiamo usato metodi costanti nei nostri esempi. Tuttavia, ci sono alcune situazioni in cui l'uso di metodi costanti sarebbe utile. Per esempio, il metodo showdist() della classe Distance, che appare ripetutamente nei nostri esempi, avrebbe dovuto essere reso costante perché non cambia (e non dovrebbe!) i campi dell'oggetto per cui viene chiamato. Ha solo lo scopo di visualizzare i valori attuali dei campi sullo schermo.

...

tratto da p. 250, Lafauré R. - Object-Oriented Programming in C++ (4th ed.) 2004

 
Dmitry Fedoseev:

Questo è ciò che si intende, perché in questo contesto non si parla di tipo. "La propria classe" è ovviamente la propria istanza (cioè l'oggetto).

Il membro_x appartiene alla stessa classe del metodo bar.

C obj._x - qui il membro _x è in una classe straniera obj.

Mi sembra accettabile parlare di una classe piuttosto che di un'istanza, perché è ovvio che _x appartiene alla nostra classe, che noi scriviamo, e obj.x alla classe straniera, che noi gestiamo.

Parlando di terminologia OOP, tutta la terminologia qui è un po' di questo (o anche molto).

Dmitry, capisci che se parli in questo modo, quelli che inizieranno a conoscere OOP con tale terminologia per la prima volta impazziranno!

Questo è quello che vuoi dire, perché non stiamo parlando di un tipo in questo contesto. "La sua classe" è ovviamente la sua istanza (cioè l'oggetto).

Probabilmente è ovvio per voi. Sto leggendo e mi chiedo come un membro _x possa appartenere a una classe se la classe è un'istruzione, un'astrazione, come tu stesso hai detto:

Forum sul trading, sistemi di trading automatico e test di strategia

Cosa significa il modificatore const dopo la dichiarazione del metodo?

Dmitry Fedoseev, 2016.02.01 19:06

Come può un oggetto chiamare un metodo? Un metodo può essere chiamato da una funzione o da un altro metodo.

Non è solo un metodo di classe che viene chiamato, ma un metodo di un oggetto specifico. La classe stessa è un'astrazione.

C obj._x - qui il membro _x è in una classe estranea obj.

Davvero non capite la differenza tra una classe e un'istanza di una classe? Non si può dire questo, assolutamente, perché farà esplodere il cervello del lettore, che penserà che l'oggetto che ha chiamato il metodo e l'oggetto obj sono istanze di classi diverse, sebbene siano istanze di una sola classe (nell'esempio che avete citato).

Parlando di terminologia OOP, tutta la terminologia qui è un po' di questo (o anche molto).

La terminologia è "un po' un problema" quando non si capisce con cosa si ha a che fare. Dovete solo capire chiaramente cos'è una classe (istruzione) e cos'è un oggetto (istanza) di una classe. E allora molti problemi spariranno da soli. Ovviamente, non sarò in grado di farti cambiare idea, quindi non vedo il motivo di continuare la discussione su questo argomento. È un peccato.
 
unreal:
Metodi costanti
I metodi costanti si distinguono per il fatto che non cambiano i valori dei loro campi di classe. Guardiamo un esempio chiamato CONSTFU:
// constfu.cpp
// применение константных методов
class aClass
{
private:
    int alpha;
public:
    void nonFunc()    // неконстантный метод
    { 
        alpha = 99;
    }      // корректно
    void conFunc()const   // константный метод
    { 
        alpha = 99;
    }    // ошибка: нельзя изменить значение поля
};

Un normale metodo nonFunc() può cambiare il valore del campo alfa, ma un metodo costante conFunc() no. Se viene fatto un tentativo di cambiare il campo alfa, il compilatore segnalerà un errore.
Per rendere una funzione una costante, la parola chiave const deve essere specificata dopo il prototipo della funzione, ma prima dell'inizio del corpo della funzione. Se la dichiarazione e la definizione della funzione sono separate, il modificatore const deve essere specificato due volte - sia nella dichiarazione della funzione che nella sua definizione. Ha senso rendere questi metodi, che leggono solo dati dal campo della classe, costanti, perché non hanno bisogno di cambiare i valori dei campi dell'oggetto classe.

L'uso di funzioni costanti aiuta il compilatore a rilevare gli errori e dice anche al lettore dell'elenco che la funzione non cambia i valori dei campi dell'oggetto. Le funzioni costanti possono essere usate per creare e usare oggetti costanti, come vedremo più avanti.

Un esempio della classe Distance

Per non includere molte innovazioni in un unico programma, finora non abbiamo usato metodi costanti nei nostri esempi. Tuttavia, ci sono alcune situazioni in cui l'uso di metodi costanti sarebbe utile. Per esempio, il metodo showdist() della classe Distance, che appare ripetutamente nei nostri esempi, avrebbe dovuto essere reso costante perché non cambia (e non dovrebbe!) i campi dell'oggetto per cui viene chiamato. Ha solo lo scopo di visualizzare i valori attuali dei campi sullo schermo.

...

tratto da p. 250, Lafauré R. - Object-Oriented Programming in C++ (4th ed.) 2004

Ma che ordine sarà nella vostra mente se anche in un libro su OOP scrivono o giusto o sbagliato. Anche se, forse, è la traduzione.
 
Alexey Kozitsyn:

Dmitry, capisci che se parli così, quelli che iniziano a conoscere l'OOP con questa terminologia per la prima volta impazziranno?

Probabilmente è ovvio per voi. Leggo e penso come un membro _x possa appartenere a una classe, se una classe è un'istruzione, un'astrazione, come hai detto tu stesso:

Davvero non capisci la differenza tra una classe e un'istanza di una classe? Non si può dire questo, assolutamente, perché causerà un'esplosione cerebrale nel lettore e penserà che l'oggetto che ha chiamato il metodo e l'oggetto obj sono istanze di classi diverse, anche se sono istanze della stessa classe (nell'esempio che avete dato).

La terminologia è poi "un po' così" quando non si capisce con cosa si ha a che fare. Dovete solo capire chiaramente cos'è una classe (istruzione) e cos'è un oggetto (istanza) di una classe. E allora molti problemi spariranno da soli. Ovviamente, non sarò in grado di farti cambiare idea, quindi non vedo il motivo di continuare la discussione su questo argomento. È un peccato.

Perché dovresti farmi cambiare idea? Cambiare idea su cosa? Per me va tutto bene. Il primo post di questo thread mi è bastato per avere una comprensione completa senza conflitti.

Notate anche che siete stati voi a scrivere che il riferimento sarebbe stato sufficiente per capire. Quindi non è affatto chiaro di cosa state discutendo?

ps. Non attribuire a me un mucchio di tue delusioni.

 
George Merts:

Personalmente, ho sempre inteso i metodi const come metodi che non possono cambiare le variabili di classe.

Li ho usati molto raramente, perché ho spesso incontrato una situazione in cui la ridefinizione di un metodo richiede di cambiare qualcosa, mentre il metodo base è costante (è già stato menzionato qui).

I metodi statici sono ampiamente utilizzati. In quasi tutte le classi complesse. Di solito questi sono metodi aggiuntivi "di servizio" che non richiedono l'accesso alle variabili di classe.

Inoltre, per le costanti come "numero di secondi in un giorno" cerco di usare una const const statica, piuttosto che #define. In questo caso, la dichiarazione e l'inizializzazione di tale costante sono in posti diversi, ma il controllo del tipo si verifica e mi aiuta più di una volta.

La stessa cosa che uso raramente. In effetti, ho iniziato l'argomento perché uno dei partecipanti a questo forum mi ha chiesto in un messaggio privato perché ne avevo bisogno.
 
George Merts:

Personalmente, ho sempre inteso i metodi const come metodi che non possono cambiare le variabili di classe.

Li ho usati molto raramente, perché più di una volta mi sono imbattuto in una situazione in cui l'override di un metodo deve cambiare qualcosa, e il metodo base è costante (è già stato menzionato qui).

Tu NON li usi per questo motivo, e io li uso per questo motivo:

zaskok3:

Per me, usare const e static aumenta notevolmente la leggibilità/comprensione del mio codice. E vi permette spesso di catturare bug o difetti nella vostra architettura all'inizio della sua implementazione.


Scrivo tutto solo per me stesso. E sembra che non cambierò alcuni dati che non dovrei comunque. Ma il desiderio di proteggermi dalla mia stessa stupidità mi fa rivettare l'architettura OOP in modo tale che solo ciò che deve essere accessibile per cambiare. Il resto no. E qui i tipi const + inheritance sono di grande aiuto. Lo raccomando.
 

Gente gentile aiuta a compilare EA molto per favore, non sono bravo a programmare.

Questo è l'errore che ottengo quando compilo 'delete' - name expected

L'errore nel codice è evidenziato in rosso

void delete(int type){

se(OrdiniTotali()>0){

for(i=OrdiniTotali()-1;i>=0;i--){

OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

if(type!=6 && type!=7 && type!=8)if(OrderSymbol()==Symbol() && OrderMagicNumber()==magico && OrderType()==type)OrderDelete(OrderTicket();

if(type==6)if(OrderSymbol()==Symbol() && OrderMagicNumber()==magico && OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP || OrderType()==OP_BUYLIMIT || OrderType()==OP_SELLLIMIT)OrderDelete(OrderTicket());

if(type==7)if(OrderSymbol()==Symbol() && OrderMagicNumber()==magico && OrderType()==OP_BUYSTOP || OrderType()==OP_BUYLIMIT)OrderDelete(OrderTicket());

if(type==8)if(OrderSymbol()==Symbol() && OrderMagicNumber()==magico && OrderType()==OP_SELLSTOP || OrderType()==OP_SELLLIMIT)OrderDelete(OrderTicket());

}

}

}


Ecco un altro errore '(' - puntatore a oggetto atteso

if(oppositedelete){delete(OP_SELLSTOP);delete(OP_SELLLIMIT);}

E qui '}' - non tutti i percorsi di controllo restituiscono un valore

int countglobal(){

int cnt=0;

se(OrdiniTotali()>0){

for(i=OrdiniTotali()-1;i>=0;i--){

OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

cnt++;

}

ritorno(cnt);

}

}

 
zaskok3:

Tu NON li usi per questo motivo, e io li uso per questo motivo:

Sono d'accordo che lo specificatore const è utile quando si leggono e si comprendono le funzioni scritte lunghe. Ma limitare l'accesso alle variabili mi sembra più sensato dichiarandole in diverse sezioni private-protette-pubbliche (personalmente non dichiaro mai variabili come pubbliche, solo metodi).

È difficile per me pensare a una situazione in cui una variabile interna di classe non dovrebbe essere modificata nei discendenti.

 
Anton Razmyslov:

Le persone gentili aiutano con la compilazione di EA molto per favore, non sono bravo a programmare.

E nella logica? Perché ingombrare un argomento non di profilo con domande come questa?
 

A proposito, nessuno ha scritto che il modificatore Const non solo non permette di cambiare i dati all'interno della propria classe, ma anche di indirizzare metodi non costanti. Un semplice esempio: c'è una classe di posizione, abbiamo bisogno di ordinare la lista delle posizioni per profitto. Il profitto è calcolato dalla richiesta:

class CPosition : public CObject
{
private:
   double m_profit;
   void CalculateProfit()
   {
      m_profit = 31337;
   }
public:
   CPosition(void) : m_profit(0.0)
   {
   }
   double Profit(void)const
   {
      if(m_profit == 0.0)
         CalculateProfit(); // <- Константный метод вызывает блок рассчета и вызывает ошибку
      return m_profit;
   }
   virtual int Compare(const CObject *node,const int mode=0) const
   {
      const CPosition* pos = node;
      if(pos.Profit() > Profit())
         return 1;
      else if(pos.Profit() < Profit())
         return -1;
      return 0;
   }
};

Questo codice causerà un errore perché anche se il metodo Profit è costante, si riferisce al metodo non costante CalcultaeProfit se il profitto non è ancora stato calcolato.

Notate che il metodo Profit è assolutamente sicuro: garantisce che il valore che restituisce non è vuoto. Tuttavia, il metodo costante richiede di abbandonare i calcoli dietro le quinte e l'alta sicurezza del codice in favore di alcune costruzioni out-of-the-box che non sanno cosa e perché limitano.

Motivazione: