Errores, fallos, preguntas - página 1183

 
Zeleniy:

Al probar el Asesor Experto, se genera un error

toma de beneficios no válida para la función OrderSend

Error de OrderSend 4107

¿Cómo puedo solucionarlo sin entrar en el código?

en los ajustes intente aumentar o disminuir el beneficio
 
mql5:
La función ZeroMemory no se puede utilizar para este objeto

Ya veo, pero ¿por qué el compilador muestra este error no en un lugar donde se utilizaZeroMemory sino en un lugar donde se define la clase? Es confuso. Ya me he devanado los sesos tratando de averiguar cuál es el error y dónde se encuentra. Por favor, asegúrese de que el error se muestra en un lugar correcto. Por ejemplo, al copiar un objeto que contiene elementos no permitidos para ser copiados, el error se produce exactamente en la línea con la copia y no en algún lugar dentro de la clase.

 
meat:

Pasando a la parte práctica de todo esto, ya me he encontrado con un problema. El código utilizaba objetos estáticos. Entonces decidí sustituir algunas de ellas por otras dinámicas. Como resultado, las operaciones de comparación y asignación empezaron a funcionar de forma muy diferente. Y este problema era difícil de detectar porque el programa sigue compilando y funcionando normalmente pero no de la manera que debería.

No entendí inmediatamente el problema

class B {};

class A {
public:
        bool operator !=( A* a ) { Print( __FUNCTION__ ); return ( true  );  }
        bool operator !=( B* b ) { Print( __FUNCTION__ ); return ( false );  }
        bool operator >>( A* a ) { Print( __FUNCTION__ ); return ( true  );  }
        bool operator +( A* a )  { Print( __FUNCTION__ ); return ( false  ); }
        bool operator !()        { Print( __FUNCTION__ ); return ( true   ); }
};

void OnStart()
{
        A *a = new A;
        B *b = new B;
        if ( a != a ) Print( "1" );
        if ( a != b ) Print( "2" );
        if ( a >> a ) Print( "3" );
        if ( !a )     Print( "4" );
        delete( a );
        delete( b );
}
De esto se desprende que (a != a) lleva a comparar punteros mientras que (a >> a) lleva a llamar al operador >>( A* )

Hay una contradicción.

No se puede cambiar el comportamiento de (a >> a) como otros operadores sobrecargados (a excepción de == y !=) porque hará imposible la siguiente construcción, ya que no se puede devolver (A) sino que sólo se puede devolver (A*).

class A {
public:
        A *operator >>( string str ) { return ( GetPointer( this ) ); }
};

void OnStart()
{
        A *a = new A;
        a << "1234" << "мы" << "всю ночь" << "тусили"; //множественное применение оператора <<
}

También será imposible utilizar plenamente los operadores sobrecargados porque no existe una operación de conversión de puntero a objeto (*a)

Lo único que queda por hacer es cambiar el comportamiento de (== y !=)

Para comparar punteros (== y !=) entre sí y con el número cero (porque otras operaciones con punteros no tienen sentido), se debe introducir una función especial como (GetPointer) o especificar explícitamente una conversión de tipo al compilador

void OnStart()
{
        A *a = new A;
        B *b = new B;
        if ( ulong(a) != ulong(b) ) Print( "2" ); //хочу сравнить указатели
         if (       a  !=       b  ) Print( "2" ); //хочу вызвать operator !=( B* )

}

De este modo, se mantendrá la posibilidad de utilizar plenamente los operadores sobrecargados y se eliminará la contradicción mencionada anteriormente

La única excepción razonable a la regla general debería seguir siendo operator=() porque


class A {
public:
        A *operator =( A* a ) { return ( GetPointer( this ) ); }
};
void OnStart()
{
        A *a = new A;
        a = a; //не должно трактоваться компилятором как вызов operator=( A* ),
                // а должно остаться как присваивание указателю значения
}
 
Y por supuesto la propuesta de utilizar (*a) al menos para los operadores - volver a la notación C++
class A {
public:
        bool operator !=( A* a ) { Print( __FUNCTION__ ); return ( true  );  }
};

void OnStart()
{
        A *a = new A;
        if (  a !=  a ) Print( 1 ); //сравнение указателей
        if ( *a != *a ) Print( 2 ); //вызов operator !=( A* )
}

eliminaría todas las contradicciones de una vez.

Corrección: en realidad, las contradicciones se eliminan sólo parcialmente, porque dicha notación (*a) no resuelve el problema del uso múltiple de los operadores (que ahora funciona con éxito con todos los operadores, excepto == y !=) - por lo que la mejor manera de comparar punteros entre sí en igualdad/desigualdad sigue siendo el uso de la función especial - o la conversión explícita al tipo ulong

 
A100, gracias por los mensajes, lo solucionaremos.
 
Error de compilación
class A {
public:
      A( int a1 ) : a3( a1 ) { }
  static int a2;
        int a3;
};
int A::a2 = 1;

void OnStart()
{
        int b = A::a2;  //нормально
        A t1( b );     //нормально
        A t2( A::a2 ); //ошибка компиляции
        A* t3 = new A( A::a2 ); //нормально
}
si un argumento miembro estático de un constructor (excepto new)
 
El compilador no permite comentarios dentro de #define después de transferir
#define  f( x )                   \
        ( x != 0 &&  /*comment*/\ 
          x != 1 )

esto está bien, y esto

#define  f( x )       \
        ( x != 0 &&  \ /*comment*/
          x != 1 )
error de compilación
 

Siguiendo con el tema de los punteros, estaría bien añadir a MQL el operador estándar de tomar un puntero'&', sería mucho más cómodo y compacto que el engorroso GetPointer.Así, teniendo los operadores * y & en nuestro arsenal, podemos definir explícitamente las operaciones necesarias:

if (&a==&b) Print("Указатели равны");
if (*a==*b) Print("Объекты равны");


Y hay más sobre este ampersand. MQL carece de referencias a variables, sobre todo teniendo en cuenta el uso limitado de punteros (sólo a objetos de clase). La función requiere a menudo el acceso a un elemento de estructura profundamente anidado o a una matriz multidimensional. Tengo que escribir la ruta completa hasta ella cada vez, lo que hace que el código sea muy engorroso.Puedes simplificar las cosas creando una referencia y a veces sólo tienes que "cambiar" el nombre de una variable localmente por conveniencia. Sin embargo, ¿qué estoy explicando aquí? Todo el mundo ya sabe lo conveniente que es usar referencias, pero ahora tienes que usar #define en su lugar, lo que ciertamente no es bueno.

Y también necesitamos la capacidad de pasar el resultado de una función por referencia, es decir, double& Func() { }

 

Facebook ha visto recientemente la aparición del backlinking de las publicaciones de los blogs:

1

 
meat:

Siguiendo con el tema de los punteros, sería bueno añadir a MQL un operador estándar de tomar un puntero'&', sería mucho más conveniente y compacto que el engorroso GetPointer.Así, al disponer de los operadores * y &, podemos definir de forma inequívoca las operaciones necesarias:

Adoptar sólo (*a) para referirse a las funciones miembro no aporta ninguna ventaja clara, sino que conduce a la imposibilidad de una aplicación múltiple simple y clara de los operadores.

class A {
public:
        A *operator >>( string str ) { Print( __FUNCTION__); return ( GetPointer( this ) ); }
};

void OnStart()
{
        A *a = new A;
        a << "1234" << "мы" << "всю ночь" << "тусили"; //простая и понятная запись

Intenta reescribirlo teniendo en cuenta tu sugerencia

void OnStart()
{
        A *a = new A;
        *(*(*(*a << "1234") << "мы") << "всю ночь") << "тусили"; //запутанная запись
}

No se puede utilizar el propio objeto en lugar del puntero porque el operador <<(...) sólo puede devolver un puntero al objeto.

¿Qué operaciones con punteros no tienen sentido? - Sólo la comparación entre sí y con un número - en consecuencia, deben ser descuidados y puestos en una función especial (por ejemplo, bool ComparePointer( a,b)) en aras de preservar la posibilidad de uso múltiple de los operadores, sin la cual la propia sobrecarga de operadores pierde su significado.