Preguntas sobre POO en MQL5 - página 83

 

Yaah... Qué lío tiene la gente con el const(((.

Para entender los métodos con especificador const

class CTest{
   int i;
public:
   CTest(int _i):i(_i){}
   int Get() const {return i;}
   int Get()   {return 2*i;}
};

void OnStart()
  {
   const CTest a(5);
   CTest b(8);
   Print(a.Get()); //5
   Print(b.Get()); //16
  }

Ahora haz

   //int Get() const {return i;}

y luego hacer lo contrario:

//   int Get()   {return 2*i;}

)))

 
Alexandr Andreev:

También una variante del mismo código.


Es con los contras.

Y estás seguro de que la entrada

Compare(CObject const *node,int const mode=0)

*siempre alimentarás*

CChartObjectRectangleX*

¿escribir sin comprobar?

return (  Time(1)-dynamic_cast<const ME*>(node).Time(1));

?

 
Alexandr Andreev:

la variante sin la constitución ya que la clase base no tiene referencia a los parámetros de entrada también funcionará correctamente, aunque este estilo no es muy inteligente

No funcionará así. No se puede cambiar la firma en Comparar. Se necesita principalmente para el método QuickSort, que se incluye en SB, para hacer que la ordenación regular funcione.

Si cambias la firma, no es un override de la función virtual sino una sobrecarga y está llamando a un método de la clase base CObject donde se devuelve 0;

Por supuesto, esto puede ser resuelto por envolturas (decoración) a los contenedores, pero ¿por qué estos movimientos innecesarios, o bien no utilizar SB y escribir todo desde cero.

 
Vladimir Simakov:

Parece ser el mismo que el tuyo, sólo que con menos letras. Así que, es cuestión de gustos, pero he eliminado la variable extra (lo más probable es que el compilador la haya eliminado como parte de la optimización).

Con respecto a mi comprobación del nodo. Debe ser sustituido por CheckPointer(node)==POINTER_INVALID, pero es una sobrecarga - una llamada a la función. Incluso si está inline, al menos está desreferenciando y comprobando la bandera de estado. Si sólo la biblioteca o el hormigón, que ha escrito el programa utilizará métodos de comparación, mejor !nodo y en el código para vigilar el puntero no válido. Si eres demasiado perezoso para estar atento a los punteros o es una biblioteca para desvalidos, sólo CheckPointer(node)==POINTER_INVALID.

Si quitas el especificador const que has resaltado, no puedes llamar a estos métodos desde un objeto constante.

UPD: la comprobación resaltada se puede eliminar, ya que está en los métodos llamados.

Vladimir, sólo en este caso CheckPointer es redundante. dynamic_cast devolverá NULL para cualquier reparto fallido, incluso si el puntero está roto. Por favor, corríjanme si me equivoco. Probado hace tiempo, la prueba duró 5 segundos).

Mecanismo de funcionamiento de CheckPointer (en palabras sencillas, no domino los términos de bajo nivel) - busca por puntero qué tipo de objeto, dinámico o estático, si no podemos obtener información, significa POINTER_INVALID. Este puede ser el caso si el objeto dinámico se eliminó, otras situaciones que no sé, o subido basura al puntero, pero debe comprobar el compilador, si no puede encontrar lagunas.

y dynamic_cast hace lo mismo, comprobando además si el puntero puede ser lanzado al tipo requerido, es decir, si es un puntero de este tipo o de una clase hija.

Si el puntero está roto, dynamic_cast no detecta nada y devuelve NULL.

Por eso no he utilizado CheckPointer. Pero suelo usar este cheque en cualquier lugar fuera de peligro. Después de todo, para encontrar un error en el software, que no se cae, un poco más fácil parece).

Y qué pasa con los no-const - en teoría podemos tener un método como GetRatingByAnyFormula() { m_rating01=Formula01(); return m_rating01;}

sería bastante incómodo si no se utilizara en la ordenación de inmediato, es decir, tendríamos que contar primero la calificación y luego llamar a la ordenación por ella. O, como ya se ha dicho, escribir su propio SB desde cero).

 
Aleksey Mavrin:

Esto no es bueno. La firma no puede ser modificada en Compare. Es principalmente con el propósito de hacer que QuickSort, el método de clasificación regular incluido en SB, funcione.

Si cambias la firma, no se trata de un overriding de la función virtual, sino de un overloading y se llamará al método de la clase base CObject, donde se devuelve 0;

Por supuesto, esto puede ser resuelto por envolturas (decoración) a los contenedores, pero ¿por qué estos movimientos innecesarios, o no utilizar SB y escribir todo desde cero?

Lo más correcto es no escribir en µl

 
Aleksey Mavrin:

Vladimir, en este caso CheckPointer es redundante. dynamic_cast devolverá NULL para cualquier lanzamiento fallido, incluso si el puntero está roto. Por favor, corríjanme si me equivoco. Probado hace tiempo, la prueba duró 5 segundos).

Mecanismo de funcionamiento de CheckPointer (en palabras sencillas, no domino los términos de bajo nivel) - busca por puntero qué tipo de objeto, dinámico o estático, si no podemos obtener información, significa POINTER_INVALID. Este puede ser el caso si el objeto dinámico se eliminó, otras situaciones que no sé, o subido basura al puntero, pero debe comprobar el compilador, si no puede encontrar lagunas.

y dynamic_cast hace lo mismo, comprobando además si el puntero puede ser lanzado al tipo requerido, es decir, si es un puntero de este tipo o de una clase hija.

Si el puntero está roto, dynamic_cast no detecta nada y devuelve NULL.

Por eso no he utilizado CheckPointer. Pero suelo usar este cheque en cualquier lugar fuera de peligro. Después de todo, para encontrar un error en el software, que no se cae, un poco más fácil parece).

Y qué pasa con los no-const - en teoría podemos tener un método como GetRatingByAnyFormula() { m_rating01=Formula01(); return m_rating01;}

sería bastante incómodo si no se utilizara en la ordenación de inmediato, es decir, tendríamos que contar primero la calificación y luego llamar a la ordenación por ella. O puede escribir su propio SB desde cero, como ya se ha mencionado).

  1. Los métodos de comparación están definidos como públicos, lo que significa que cualquier infractor, por mucho que intente explicarlo en la especificación, meterá allí un descriptor no válido. Por supuesto, si no es una biblioteca, sino sólo para ti, no tienes que hacerlo.
  2. No sé cómo funciona CheckPointer, hay hasta . Pero en cualquier caso es el reloj del procesador y el acceso a la memoria (podría resultar fácilmente la memoria virtual también).
  3. Sobre los métodos con el especificador const. Si usted escribe una biblioteca, siempre hay que tener en cuenta que el objeto puede necesitar una constante, por lo que en los métodos, que no cambian el estado del objeto, ya que es deseable. Aunque, hasta ahora, para mí, no me molesta mucho.
  4. Al escribir su propio sistema, esta es probablemente la decisión correcta. Eso es sólo perspectivas interesantes en la relación salario / trabajo no es visible todavía, y por lo tanto no se terminará, por lo que sólo para sus propias necesidades).
 
Vladimir Simakov:

Sobre mi comprobación del nodo. Debería ser reemplazado por CheckPointer(node)==POINTER_INVALID, pero esto es una sobrecarga, llamada a la función.

El problema no estará en la sobrecarga, sino en el hecho de que un puntero roto cambiará la lógica del programa, es decir, en lugar de detectar el problema, lo enterrará aún más.

CheckPointer sólo debe utilizarse para fines de depuración, o como una implementación de un puntero débil.

 
Vladimir Simakov:
  1. Los métodos de comparación están definidos como públicos, por lo que cualquier infractor, por mucho que se lo digas en la especificación, meterá ahí un descriptor no válido (llamemos a las cosas por su nombre). Por supuesto, si no es una biblioteca, sino sólo para ti, no es necesario.
  2. No sé cómo funciona CheckPointer, hay hasta . Pero en cualquier caso es el reloj del procesador y el acceso a la memoria (podría resultar fácilmente la memoria virtual también).
  3. Sobre los métodos con el especificador const. Si usted escribe una biblioteca, siempre hay que tener en cuenta que el objeto puede necesitar una constante, por lo que en los métodos, que no cambian el estado del objeto, ya que es deseable. Sin embargo, hasta ahora, en lo que a mí respecta, no me molesta.
  4. Al escribir su propio sistema, esta es probablemente la decisión correcta. Eso es sólo perspectivas interesantes en la relación salario / trabajo no es visible todavía, y por lo tanto no será llevado a, por lo que sólo para sus propias necesidades).

1. No hay discusión, pero lo que yo decía es que NO se necesita un CheckPointer (ni siquiera para los underdogs), porque dynamic_cast NO puede devolver un puntero no válido, sólo NULL.

2. Es incluso interesante, pero no se me ocurre inmediatamente un ejemplo que permita obtener un puntero no inválido que no sea matar el objeto dinámico o "ensuciar" directamente la memoria mientras se trabaja en él.

Supongo que todavía existen esas formas, pero lo más probable es que todas se sitúen en el plano de la omisión de las comprobaciones del compilador.

3,4 De acuerdo.

P.D.

Debo haberme equivocado con el 1er. La prueba dice lo contrario. Debe ser sólo una impresión).

void OnStart()
  {
      CChartObjectRectangle *base = new CChartObjectRectangle();
      CChartObjectRectangleX *rect = new CChartObjectRectangleX();
       CChartObjectRectangle * dbase  ;
      const CChartObjectRectangleX *drect  ;
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL," check? ",!dbase, " broken? ", EnumToString( CheckPointer(dbase) ));
      dbase=dynamic_cast< CChartObjectRectangle *>  (base);
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL, " check? ",!dbase," broken? ", EnumToString( CheckPointer(dbase) ));
      delete base;
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL," check? ",!dbase, " broken? ", EnumToString( CheckPointer(dbase) ));
      dbase=dynamic_cast< CChartObjectRectangle *>  (base);   
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL," check? ",!dbase, " broken? ", EnumToString( CheckPointer(dbase) ));   
  }
 
¿Es posible declarar un array estático en la sección pública de la clase e inicializarlo en el constructor? (como abajo) (¿o sólo elemento por elemento?)
 bool Mass[5] = { false, true, false, true, true };
 
Pavel Verveyko:
¿Se puede declarar un array estático en la sección pública de la clase e inicializarlo en el constructor? (como abajo) (¿o sólo elemento por elemento?)

Puedes inicializar un array local y realizar un ArrayCopy al campo del array correspondiente:

class A{
public:
   bool Mass[5];
   A(){
       bool mass_init[5] = { false, true, false, true, true };
       ArrayCopy(Mass, mass_init);
   }
};
Razón de la queja: