Qué significa el modificador const después de una declaración de método - página 6

 
Métodos constantes
Los métodos constantes se distinguen por el hecho de que no cambian los valores de sus campos de clase. Veamos un ejemplo llamado CONSTFU:
// constfu.cpp
// применение константных методов
class aClass
{
private:
    int alpha;
public:
    void nonFunc()    // неконстантный метод
    { 
        alpha = 99;
    }      // корректно
    void conFunc()const   // константный метод
    { 
        alpha = 99;
    }    // ошибка: нельзя изменить значение поля
};

Un método normal noFunc() puede cambiar el valor del campo alfa, pero un método constante conFunc() no. Si se intenta cambiar el campo alfa, el compilador informará de un error.
Para convertir una función en una constante, la palabra clave const debe especificarse después del prototipo de la función, pero antes del comienzo del cuerpo de la función. Si la declaración y la definición de la función están separadas, el modificador const debe especificarse dos veces, tanto en la declaración de la función como en su definición. Tiene sentido hacer que esos métodos, que sólo leen datos del campo de la clase, sean constantes, porque no necesitan cambiar los valores de los campos del objeto de la clase.

El uso de funciones constantes ayuda al compilador a detectar errores y también indica al lector del listado que la función no cambia los valores de los campos del objeto. Las funciones constantes pueden utilizarse para crear y utilizar objetos constantes, como veremos más adelante.

Un ejemplo de la clase Distancia

Para no incluir muchas innovaciones en un solo programa, hasta ahora no hemos utilizado métodos constantes en nuestros ejemplos. Sin embargo, hay bastantes situaciones en las que sería útil utilizar métodos constantes. Por ejemplo, el método showdist() de la clase Distance, que aparece repetidamente en nuestros ejemplos, debería haberse hecho constante porque no cambia (¡y no debería!) los campos del objeto para el que se llama. Su objetivo es únicamente mostrar los valores actuales de los campos en la pantalla.

...

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

 
Dmitry Fedoseev:

Esto es lo que se quiere decir, porque en este contexto no se habla de tipo. "Clase propia" es obviamente su propia instancia (es decir, objeto).

El miembro_x pertenece a la misma clase que el método bar.

C obj._x - aquí el miembro _x está en una clase ajena obj.

Me parece aceptable hablar de una clase en lugar de una instancia, porque es obvio que _x pertenece a nuestra clase, que escribimos, y obj.x a la clase ajena, que manejamos.

Hablando de terminología OOP, toda la terminología aquí es un poco de eso (o incluso mucho).

Dmitry, ¿comprendes que si hablas así, los que empiecen a conocer la OOP con esa terminología por primera vez se volverán locos?

Eso es lo que quiere decir porque no estamos hablando de un tipo en este contexto. "Su clase" es obviamente su propia instancia (es decir, objeto).

Probablemente sea obvio para ti. Estoy leyendo y me pregunto cómo un miembro _x puede pertenecer a una clase si la clase es una instrucción, una abstracción, como tú mismo has dicho:

Foro sobre comercio, sistemas de comercio automatizados y pruebas de estrategias

¿Qué significa el modificador const después de la declaración del método?

Dmitry Fedoseev, 2016.02.01 19:06

¿Cómo puede un objeto llamar a un método? Un método puede ser llamado desde una función o desde otro método.

No se llama sólo a un método de la clase, sino a un método de un objeto específico. La propia clase es una abstracción.

C obj._x - aquí el miembro _x está en una clase ajena obj.

¿De verdad no entiendes la diferencia entre una clase y una instancia de una clase? No puedes decir eso, de ninguna manera, porque hará que el cerebro del lector estalle, y pensará que el objeto que llamó al método y el objeto obj son instancias de clases diferentes, aunque son instancias de una clase (en el ejemplo que citaste).

Hablando de terminología OOP, toda la terminología aquí es un poco de eso (o incluso mucho).

La terminología es "un poco" cuando no se entiende lo que se está tratando. Sólo hay que entender claramente qué es una clase (instrucción) y qué es un objeto (instancia) de una clase. Y entonces muchos problemas desaparecerán por sí solos. Obviamente, no podré hacer que cambies de opinión, así que no veo ningún sentido en continuar la discusión sobre este tema. Es una pena.
 
unreal:
Métodos constantes
Los métodos constantes se distinguen por el hecho de que no cambian los valores de sus campos de clase. Veamos un ejemplo llamado CONSTFU:
// constfu.cpp
// применение константных методов
class aClass
{
private:
    int alpha;
public:
    void nonFunc()    // неконстантный метод
    { 
        alpha = 99;
    }      // корректно
    void conFunc()const   // константный метод
    { 
        alpha = 99;
    }    // ошибка: нельзя изменить значение поля
};

Un método normal noFunc() puede cambiar el valor del campo alfa, pero un método constante conFunc() no. Si se intenta cambiar el campo alfa, el compilador informará de un error.
Para convertir una función en una constante, la palabra clave const debe especificarse después del prototipo de la función, pero antes del comienzo del cuerpo de la función. Si la declaración y la definición de la función están separadas, el modificador const debe especificarse dos veces, tanto en la declaración de la función como en su definición. Tiene sentido hacer que esos métodos, que sólo leen datos del campo de la clase, sean constantes, porque no necesitan cambiar los valores de los campos del objeto de la clase.

El uso de funciones constantes ayuda al compilador a detectar errores y también indica al lector del listado que la función no cambia los valores de los campos del objeto. Las funciones constantes pueden utilizarse para crear y utilizar objetos constantes, como veremos más adelante.

Un ejemplo de la clase Distancia

Para no incluir muchas innovaciones en un solo programa, hasta ahora no hemos utilizado métodos constantes en nuestros ejemplos. Sin embargo, hay bastantes situaciones en las que sería útil utilizar métodos constantes. Por ejemplo, el método showdist() de la clase Distance, que aparece repetidamente en nuestros ejemplos, debería haberse hecho constante porque no cambia (¡y no debería!) los campos del objeto para el que se llama. Su objetivo es únicamente mostrar los valores actuales de los campos en la pantalla.

...

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

Pero qué orden tendrá en su mente si hasta en un libro sobre OOP escriben bien o mal. Aunque, tal vez, sea la traducción.
 
Alexey Kozitsyn:

Dmitry, ¿comprendes que si hablas así, los que empiezan a conocer la OOP con esa terminología por primera vez se volverán locos?

Probablemente sea obvio para ti. Estoy leyendo y pensando cómo un miembro _x puede pertenecer a una clase, si una clase es una instrucción, una abstracción, como tú mismo has dicho:

¿De verdad no entiendes la diferencia entre una clase y una instancia de una clase? No puedes decir eso, de ninguna manera, porque provocará una explosión cerebral en el lector y pensará que el objeto que llamó al método y el objeto obj son instancias de clases diferentes, aunque sean instancias de la misma clase (en el ejemplo que has puesto).

La terminología es entonces "un poco de eso" cuando no se entiende lo que se está tratando. Sólo hay que entender claramente qué es una clase (instrucción) y qué es un objeto (instancia) de una clase. Y entonces muchos problemas desaparecerán por sí solos. Obviamente, no podré hacer que cambie de opinión, así que no veo ningún sentido en continuar la discusión sobre este tema. Es una pena.

¿Por qué debería cambiar de opinión? ¿Cambiar de opinión sobre qué? Todo está bien para mí. El primer post de este hilo me ha bastado para tener una comprensión total sin conflictos.

Además, ten en cuenta que fuiste tú quien escribió que la referencia sería suficiente para entender. Así que no está nada claro qué es lo que estás argumentando.

ps. No me atribuyas un montón de tus propios delirios.

 
George Merts:

Personalmente, siempre he entendido los métodos const como métodos que no pueden modificar las variables de la clase.

Los he utilizado muy raramente, porque a menudo me he encontrado con una situación en la que la redefinición de un método requiere cambiar algo, mientras que el método base es constante (ya se mencionó aquí).

Los métodos estáticos se utilizan mucho. En casi cualquier clase compleja. Normalmente son métodos adicionales "de servicio" que no requieren acceso a las variables de la clase.

Además, para las constantes como "número de segundos en un día", intento utilizar una construcción const estática en lugar de #define. En este caso, la declaración y la inicialización de dicha constante están en lugares diferentes, pero el control de tipos se produce y me ayuda más de una vez.

Lo mismo que rara vez uso. De hecho, inicié el tema porque uno de los participantes de este foro me preguntó en un mensaje privado por qué los necesitaba.
 
George Merts:

Personalmente, siempre he entendido los métodos const como métodos que no pueden modificar las variables de la clase.

Los he usado muy pocas veces, porque más de una vez me he encontrado con una situación en la que un método override necesita cambiar algo, y el método base es constante (ya se ha mencionado aquí).

Tú NO los usas por esa razón, y yo sí los uso por esa razón:

zaskok3:

Para mí, el uso de const y static aumenta enormemente la legibilidad/comprensión de mi propio código. Y le permite detectar a menudo errores o fallos en su propia arquitectura en una fase temprana de su implementación.


Lo escribo todo sólo para mí. Y parece que no voy a cambiar algunos datos que no debería de todos modos. Pero el deseo de protegerme de mi propia estupidez me hace remachar la arquitectura OOP de tal manera, que sólo lo que debe ser accesible para cambiar. El resto no lo es. Y aquí los tipos de const + herencia son de gran ayuda. Lo recomiendo.
 

La gente amable ayuda con la compilación de EA muy por favor, no soy bueno en la programación.

Este es el error que obtengo al compilar 'delete' - nombre esperado

El error en el código está resaltado en rojo

void delete(int type){

if(OrdersTotal()>0){

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

OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

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

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

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

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

}

}

}


Aquí hay otro error '(' - se esperaba un puntero de objeto

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

Y aquí "} - no todas las vías de control devuelven un valor

int countglobal(){

int cnt=0;

if(OrdersTotal()>0){

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

OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

cnt++;

}

return(cnt);

}

}

 
zaskok3:

Tú NO los usas por esta razón, y yo sí los uso por esta razón:

Estoy de acuerdo en que el especificador const es útil a la hora de leer y entender funciones escritas de forma larga. Pero restringir el acceso a las variables me parece que tiene más sentido declarándolas en diferentes secciones privadas-protegidas-públicas (yo personalmente nunca declaro variables como públicas, sólo métodos).

Me resulta difícil pensar en una situación en la que una variable interna de la clase no deba ser modificada en los descendientes.

 
Anton Razmyslov:

La gente amable ayuda con la compilación de EA muy por favor, no es bueno en la programación.

¿Y en la lógica? ¿Por qué abarrotar un tema que no es de perfil con preguntas como ésta?
 

Por cierto, nadie escribió que el modificador Const no sólo no permite cambiar los datos dentro de la propia clase, sino incluso abordar métodos no constantes. Un ejemplo sencillo: hay una clase de posición, necesitamos ordenar la lista de posiciones por beneficio. El beneficio se calcula según la solicitud:

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

Este código causará un error porque aunque el método Profit es constante, hace referencia al método no constante CalcultaeProfit si el beneficio no ha sido calculado todavía.

Tenga en cuenta que el método Profit en sí mismo es absolutamente seguro: garantiza que el valor que devuelve no está vacío. Sin embargo, el método constante requiere abandonar los cálculos entre bastidores y la alta seguridad del código en favor de algunas construcciones "out-of-the-box" que no saben qué y por qué limitan.