Fehler, Irrtümer, Fragen - Seite 1183

 
Zeleniy:

Beim Testen des Expert Advisors wird ein Fehler erzeugt

Ungültige Gewinnmitnahme bei der Funktion OrderSend

OrderSend-Fehler 4107

Wie kann ich das Problem beheben, ohne in den Code zu gehen?

in den Einstellungen versuchen, den Gewinn zu erhöhen oder zu verringern
 
mql5:
Die Funktion ZeroMemory kann für dieses Objekt nicht verwendet werden.

Verstehe. Aber warum zeigt der Compiler diesen Fehler nicht an einer Stelle an, an derZeroMemory verwendet wird, sondern an einer Stelle, an der die Klasse definiert ist? Das ist verwirrend. Ich habe mir schon das Hirn zermartert, um herauszufinden, was der Fehler ist und wo er sich befindet. Bitte stellen Sie sicher, dass der Fehler an der richtigen Stelle angezeigt wird. Wenn Sie zum Beispiel ein Objekt kopieren, das Elemente enthält, die nicht kopiert werden dürfen, tritt der Fehler genau in der Zeile mit dem Kopieren auf und nicht irgendwo innerhalb der Klasse.

 
meat:

Was die praktische Seite betrifft, so bin ich bereits auf ein Problem gestoßen. Der Code verwendete statische Objekte. Dann habe ich beschlossen, einige von ihnen durch dynamische zu ersetzen. Dies hatte zur Folge, dass die Vergleichs- und Zuweisungsoperationen nun ganz anders funktionierten. Und dieses Problem war schwer zu erkennen, weil das Programm weiterhin kompiliert und normal funktioniert, aber nicht so, wie es sollte.

Ich habe das Problem nicht sofort verstanden

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 );
}
Daraus können Sie ersehen, dass (a != a) zu einem Vergleich von Zeigern führt, während (a >> a) zum Aufruf des Operators >>( A* ) führt

Das ist ein Widerspruch.

Sie können das Verhalten von (a >> a) nicht wie andere überladene Operatoren (mit Ausnahme von == und !=) ändern, da dies das folgende Konstrukt unmöglich machen würde, da Sie nicht (A), sondern nur (A*) zurückgeben können.

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

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

Es wird auch nicht möglich sein, überladene Operatoren in vollem Umfang zu verwenden, da es keine Zeiger-zu-Objekt-Umwandlungsoperation gibt (*a)

Das Einzige, was noch zu tun ist, ist, das (== und !=) Verhalten zu ändern

Um Zeiger (== und !=) miteinander und mit der Zahl Null zu vergleichen (weil andere Zeigeroperationen sinnlos sind), sollte man eine spezielle Funktion wie (GetPointer) einführen oder dem Compiler explizit eine Typumwandlung vorgeben

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

}

Damit bleibt die Möglichkeit der uneingeschränkten Verwendung von überladenen Operatoren erhalten und der oben erwähnte Widerspruch wird beseitigt

Die einzige vernünftige Ausnahme von der allgemeinen Regel sollte operator=() bleiben, weil


class A {
public:
        A *operator =( A* a ) { return ( GetPointer( this ) ); }
};
void OnStart()
{
        A *a = new A;
        a = a; //не должно трактоваться компилятором как вызов operator=( A* ),
                // а должно остаться как присваивание указателю значения
}
 
Und natürlich der Vorschlag, (*a) zumindest für Operatoren zu verwenden - zurück zur C++-Notation
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* )
}

würde alle Widersprüche auf einen Schlag beseitigen.

Korrektur: tatsächlich werden Widersprüche nur teilweise beseitigt, weil diese Notation (*a) das Problem der Mehrfachverwendung von Operatoren nicht löst (was jetzt erfolgreich mit allen Operatoren außer == und != funktioniert) - der beste Weg, Zeiger auf Gleichheit/Ungleichheit miteinander zu vergleichen, ist also immer noch die Verwendung einer speziellen Funktion - oder die explizite Umwandlung in den Typ ulong

 
A100, vielen Dank für die Nachrichten, wir werden das in Ordnung bringen.
 
Kompilierungsfehler
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 ); //нормально
}
wenn ein statisches Mitgliedsargument eines Konstruktors (außer new)
 
Der Compiler erlaubt keine Kommentare innerhalb von #define nach der Übergabe
#define  f( x )                   \
        ( x != 0 &&  /*comment*/\ 
          x != 1 )

das ist gut, und das

#define  f( x )       \
        ( x != 0 &&  \ /*comment*/
          x != 1 )
Kompilierungsfehler
 

Fortsetzung des Themas über Zeiger, wäre es schön, MQL-Standard-Operator der Einnahme eines Zeigers'&' hinzufügen, wäre es viel bequemer und kompakter als umständlich GetPointer.Da wir die Operatoren * und & in unserem Arsenal haben, können wir die notwendigen Operationen explizit definieren:

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


Und es gibt noch mehr über dieses kaufmännische Und. In MQL fehlt ein Verweis auf Variablen, insbesondere wenn man die begrenzte Verwendung von Zeigern (nur auf Klassenobjekte) berücksichtigt. Die Funktion erfordert oft den Zugriff auf ein tief verschachteltes Strukturelement oder ein mehrdimensionales Array. Ich muss jedes Mal den vollständigen Pfad dazu schreiben, was den Code sehr umständlich macht.Man kann die Dinge vereinfachen, indem man eine Referenz erstellt, und manchmal muss man den Namen einer Variablen der Einfachheit halber lokal "ändern". Aber was erkläre ich hier? Jeder weiß bereits, wie praktisch es ist, Referenzen zu verwenden, aber jetzt muss man stattdessen #define verwenden, was sicherlich nicht gut ist.

Und wir brauchen auch die Möglichkeit, das Ergebnis einer Funktion per Referenz zu übergeben, d.h. double& Func() { }

 

Facebook hat vor kurzem das Backlinking von Beiträgen aus Blogs eingeführt:

1

 
meat:

Um beim Thema Zeiger zu bleiben, wäre es gut, MQL einen Standard-Operator hinzuzufügen, mit dem man einen Zeiger'&' nehmen kann. Das wäre viel bequemer und kompakter als das umständliche GetPointer.Damit entfällt auch das oben beschriebene Casting mit ulong, so dass wir mit den Operatoren * und & die notwendigen Operationen eindeutig definieren können:

Die ausschließliche Verwendung von (*a) für den Verweis auf Mitgliedsfunktionen bringt keine eindeutigen Vorteile, sondern macht es unmöglich, die Operatoren auf einfache und klare Weise zu verwenden.

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

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

Versuchen Sie, ihn unter Berücksichtigung Ihres Vorschlags neu zu schreiben

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

Sie können nicht das Objekt selbst anstelle des Zeigers verwenden, da der Operator <<(...) nur einen Zeiger auf das Objekt zurückgeben kann.

Welche Operationen mit Zeigern sind sinnlos? - Nur Vergleiche untereinander und mit einer Zahl - daher sollten wir sie vernachlässigen und in eine spezielle Funktion (z.B. bool ComparePointer( a,b)) packen, um die Möglichkeit der Mehrfachverwendung von Operatoren zu erhalten, ohne die die Operatorüberladung selbst ihre entscheidende Bedeutung verliert.

Grund der Beschwerde: