Errori, bug, domande - pagina 1183

 
Zeleniy:

Quando si testa l'Expert Advisor, genera un errore

takeprofit non valido per la funzione OrderSend

Errore 4107 di OrderSend

Come posso risolvere il problema senza entrare nel codice?

nelle impostazioni provare ad aumentare o diminuire il takeprofit
 
mql5:
La funzione ZeroMemory non può essere usata per questo oggetto

Capisco, ma perché il compilatore mostra questo errore non in un posto dove si usaZeroMemory, ma in un posto dove la classe è definita? È confuso. Mi sono già scervellato cercando di capire qual è l'errore e dove si trova. Per favore, assicurati che l'errore sia mostrato in un posto giusto. Per esempio, quando si copia un oggetto che contiene elementi che non possono essere copiati, l'errore si verifica esattamente nella linea con la copia e non da qualche parte dentro la classe.

 
meat:

Venendo al lato pratico di tutto questo, ho già incontrato un problema. Il codice usava oggetti statici. Poi ho deciso di sostituirne alcuni con altri dinamici. Come risultato, le operazioni di confronto e di assegnazione hanno iniziato a funzionare in modo molto diverso. E questo problema era difficile da rilevare perché il programma continua a compilare e a funzionare normalmente ma non nel modo in cui dovrebbe.

Non ho capito subito il 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 );
}
Da questo si può vedere che (a != a) porta al confronto dei puntatori mentre (a >> a) porta a chiamare l'operatore >>( A* )

C'è una contraddizione.

Non potete cambiare il comportamento di (a >> a) come gli altri operatori sovraccaricati (eccetto == e !=) perché renderà impossibile il seguente costrutto, poiché non potete restituire (A) ma potete solo restituire (A*).

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

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

Sarà anche impossibile utilizzare completamente gli operatori sovraccaricati perché non esiste un'operazione di conversione puntatore-oggetto (*a)

L'unica cosa rimasta da fare è cambiare il comportamento (== e !=)

Per confrontare i puntatori (== e !=) tra loro e con il numero zero (perché le altre operazioni con i puntatori non hanno senso), si dovrebbe introdurre una funzione speciale come (GetPointer) o specificare esplicitamente una conversione di tipo al compilatore

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

}

Così, la possibilità di utilizzare pienamente gli operatori sovraccaricati sarà preservata e la contraddizione sopra menzionata sarà eliminata

L'unica eccezione ragionevole alla regola generale dovrebbe rimanere operator=() perché


class A {
public:
        A *operator =( A* a ) { return ( GetPointer( this ) ); }
};
void OnStart()
{
        A *a = new A;
        a = a; //не должно трактоваться компилятором как вызов operator=( A* ),
                // а должно остаться как присваивание указателю значения
}
 
E naturalmente la proposta di usare (*a) almeno per gli operatori - tornare alla notazione 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* )
}

eliminerebbe tutte le contraddizioni in una volta sola.

Correzione: in realtà, le contraddizioni sono eliminate solo parzialmente, perché tale notazione (*a) non risolve il problema dell'uso multiplo degli operatori (che ora funziona con successo con tutti gli operatori, tranne == e !=) - quindi il modo migliore per confrontare i puntatori tra loro su uguaglianza/disuguaglianza è ancora utilizzando la funzione speciale - o la conversione esplicita al tipo ulong

 
A100, grazie per i messaggi, risolveremo il problema.
 
Errore di compilazione
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 un argomento membro statico di un costruttore (eccetto new)
 
Il compilatore non permette commenti dentro #define dopo il trasferimento
#define  f( x )                   \
        ( x != 0 &&  /*comment*/\ 
          x != 1 )

questo va bene, e questo

#define  f( x )       \
        ( x != 0 &&  \ /*comment*/
          x != 1 )
errore di compilazione
 

Continuando il tema dei puntatori, sarebbe bello aggiungere a MQL l'operatore standard di prendere un puntatore'&', sarebbe molto più comodo e compatto dell'ingombrante GetPointer.Così, avendo gli operatori * e & nel nostro arsenale, saremo in grado di definire esplicitamente le operazioni necessarie:

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


E c'è di più su questa ampersand. MQL manca di riferimenti alle variabili, soprattutto tenendo conto dell'uso limitato dei puntatori (solo agli oggetti di classe). La funzione richiede spesso l'accesso a un elemento di struttura profondamente annidato o a un array multidimensionale. Devo scrivere il percorso completo ad esso ogni volta, il che rende il codice molto ingombrante.Puoi semplificare le cose creando un riferimento e a volte devi solo "cambiare" il nome di una variabile localmente per comodità. Tuttavia, cosa sto spiegando qui? Tutti sanno già quanto sia conveniente usare i riferimenti, ma ora devi usare #define invece, il che non è certamente buono.

E abbiamo anche bisogno della capacità di passare il risultato di una funzione per riferimento, cioè double& Func() { }

 

Facebook ha recentemente visto l'emergere del backlinking dei post dai blog:

1

 
meat:

Restando in tema di puntatori, sarebbe bene aggiungere a MQL un operatore standard per prendere un puntatore'&', sarebbe molto più comodo e compatto dell'ingombrante GetPointer.Così, avendo gli operatori * e &, possiamo definire senza ambiguità le operazioni necessarie:

Adottare solo (*a) per riferirsi alle funzioni membro non dà vantaggi evidenti, ma porta invece all'impossibilità di una semplice e chiara applicazione multipla degli operatori.

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

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

Prova a riscriverlo tenendo conto del tuo suggerimento

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

Non potete usare l'oggetto stesso al posto del puntatore perché l'operatore <<(...) può restituire solo un puntatore all'oggetto.

Quali operazioni con i puntatori sono senza senso? - Solo il confronto tra loro e con un numero - di conseguenza, dovrebbero essere trascurati e messi in una funzione speciale (per esempio, bool ComparePointer( a,b)) per preservare la possibilità di un uso multiplo degli operatori senza il quale l'overload degli operatori stessi perde il suo significato.