Erros, bugs, perguntas - página 1183

 
Zeleniy:

Ao testar o Expert Advisor, ele gera um erro

lucro takeprofit inválido para a função OrderSend

Erro de encomendaEnviar 4107

Como posso corrigi-lo sem entrar no código?

nos cenários tentam aumentar ou diminuir o takeprofit
 
mql5:
A função ZeroMemory não pode ser utilizada para este objecto

Mas porque é que o compilador mostra este erro não num local onde aZeroMemory é utilizada, mas num local onde a classe é definida? É confuso. Por exemplo, ao copiar um objecto que contém itens que não podem ser copiados, o erro ocorre exactamente na linha com a cópia e não algures dentro da classe.

 
meat:

Chegados ao lado prático de tudo isto, já me deparei com um problema. O código estava a utilizar objectos estáticos. Depois decidi substituir algumas delas por outras dinâmicas. Como resultado, as operações de comparação e atribuição começaram a funcionar de forma bastante diferente. E este problema era difícil de detectar porque o programa continua a compilar e a funcionar normalmente, mas não da forma que deveria.

Não compreendi imediatamente o 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 );
}
A partir disto pode ver que (a != a) leva à comparação de apontadores enquanto (a >> a) leva ao operador de chamada >>( A* )

Há uma contradição.

Não pode alterar o comportamento de (a >> a) como outros operadores sobrecarregados (excepto para == e !=) porque tornará impossível a seguinte construção, uma vez que não pode regressar (A) mas só pode regressar (A*).

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

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

Também será impossível utilizar plenamente operadores sobrecarregados porque não existe uma operação de conversão de ponteiro para objecto (*a)

A única coisa a fazer é alterar o (== e !=) comportamento

Para comparar apontadores (== e !=) entre si e com o número zero (porque outras operações de ponteiro não têm significado), deve-se introduzir uma função especial como (GetPointer) ou especificar explicitamente uma conversão de tipo para o 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* )

}

Assim, a possibilidade de utilização plena de operadores sobrecarregados será preservada e a contradição acima mencionada será eliminada

A única excepção razoável à regra geral deve permanecer operador=() porque


class A {
public:
        A *operator =( A* a ) { return ( GetPointer( this ) ); }
};
void OnStart()
{
        A *a = new A;
        a = a; //не должно трактоваться компилятором как вызов operator=( A* ),
                // а должно остаться как присваивание указателю значения
}
 
E, claro, a proposta de utilizar (*a) pelo menos para os operadores - voltar à notação 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* )
}

eliminaria todas as contradições de uma só vez.

Correcção: na verdade, as contradições são eliminadas apenas parcialmente, porque tal notação (*a) não resolve o problema da utilização múltipla de operadores (que agora funciona com sucesso com todos os operadores, excepto == e !=) - por isso a melhor forma de comparar apontadores entre si sobre igualdade/inequalidade continua a utilizar uma função especial - ou conversão explícita para o tipo ulong

 
A100, obrigado pelas mensagens, vamos resolvê-lo.
 
Erro de compilação
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 ); //нормально
}
se um argumento de membro estático de um construtor (excepto novo)
 
O compilador não permite comentários dentro de #define após a transferência
#define  f( x )                   \
        ( x != 0 &&  /*comment*/\ 
          x != 1 )

isto está bem, e isto

#define  f( x )       \
        ( x != 0 &&  \ /*comment*/
          x != 1 )
erro de compilação
 

Continuando o tema sobre apontadores, seria bom acrescentar ao operador padrão MQL um apontador'&', seria muito mais conveniente e compacto do que o pesado GetPointer.Assim, tendo * e & operadores no nosso arsenal, podemos definir explicitamente as operações necessárias:

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


E há mais sobre este ampersand. MQL carece de referência a variáveis, especialmente tendo em conta o uso limitado de apontadores (apenas para objectos de classe). A função requer frequentemente acesso a um elemento de estrutura profundamente aninhado ou a uma matriz multidimensional. Tenho de escrever o caminho completo para ele cada vez, o que torna o código muito pesado.Pode-se simplificar as coisas criando uma referência e por vezes basta "mudar" o nome de uma variável localmente por conveniência. No entanto, o que estou a explicar aqui? Toda a gente já sabe como é conveniente usar referências, mas agora é preciso usar #define em vez disso, o que certamente não é bom.

E também precisamos da capacidade de passar o resultado de uma função por referência, ou seja, double& Func() { } { }

 

O Facebook assistiu recentemente ao surgimento de retroligações de posts de blogs:

1

 
meat:

Mantendo o tema dos apontadores, seria bom acrescentar à MQL um operador padrão de tomar um apontador'&', seria muito mais conveniente e compacto do que o pesado GetPointer.Assim, tendo os * e & operadores, podemos definir sem ambiguidade as operações necessárias:

Adoptar apenas (*a) para se referir às funções dos membros não dá quaisquer vantagens claras, mas em vez disso torna impossível a utilização dos operadores de uma forma simples e clara.

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

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

Tente reescrevê-lo tendo em conta a sua sugestão

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

Não se pode usar o objecto em si em vez do ponteiro porque o operador <<(...) só pode devolver um ponteiro ao objecto.

Que operações com apontadores não têm sentido? - Apenas comparação entre si e com um número - por isso devemos negligenciá-los e colocá-los numa função especial (por exemplo, bool ComparePointer( a,b)) para preservar a possibilidade de utilização múltipla de operadores sem os quais o próprio operador se sobrecarrega perde o seu significado crucial.