Ist es möglich, ein Singleton-Muster in MQL4 zu implementieren. - Seite 9

 
hoz:

Ich habe es auf diese Weise gemacht:

Aber aus irgendeinem Grund kommt es beim Kompilieren zu einer Menge Fehler. Was ist los?

Der Versuch, ein recht einfaches Singleton von Myers nach MQL4++ zu übertragen, könnte z.B. so aussehen:

#property strict

/******************************************************************************/
class Symbol_Properties {
private:
   // Реализация технической части singleton'а
  /******************************************************************************/
public: // Вечно в этом MQL4++ что-то не работает: 'Symbol_Properties::Symbol_Prope…' - cannot call private member function
  Symbol_Properties() {};
private: // Восстанавливаем private
  Symbol_Properties(const Symbol_Properties &p);
  void operator =(const Symbol_Properties &);

public:
  static Symbol_Properties *singleton() {
    static Symbol_Properties sp;
    return GetPointer(sp);
  }

  // Пользовательская часть singleton'а
  /******************************************************************************/
  datetime    gdt_Quote;           // Время поступления последней котировки
  double      gda_Price [2];       // Текущие рыночные цены (0 - Bid, 1- Ask)
  double      gd_Spread;           // Размер спреда в пунктах
  double      gd_Swap;             // Своп
  double      gd_Comission;        // Комиссия
  double      gd_Pt;               // Величина одного пункта
  int         gi_Digits;           // Количество знаков в цене после запятой
  int         gi_StopLevel;        // Минимально-допустимый уровень стоп-лосса/тейк-профита в пунктах
  int         gi_FreezLevel;       // Уровень заморозки ордеров в пунктах
};

/******************************************************************************/
void change() {
  Symbol_Properties *p = Symbol_Properties::singleton(); // Получение singleton'а

  p.gdt_Quote = TimeCurrent();
  p.gda_Price[0] = Bid;
  p.gda_Price[1] = Ask;
}

/******************************************************************************/
void OnStart() {
  Symbol_Properties *p = Symbol_Properties::singleton(); // Получение singleton'а

  Print("gdt_Quote = ", p.gdt_Quote, ", Price = ", p.gda_Price[0], "/", p.gda_Price[1]);
  change();
  Print("gdt_Quote = ", p.gdt_Quote, ", Price = ", p.gda_Price[0], "/", p.gda_Price[1]);
}

Ergebnis der Ausführung:

01:24:57 Script 3 EURUSDm,H1: loaded successfully
01:24:57 3 EURUSDm,H1: initialized
01:24:57 3 EURUSDm,H1: gdt_Quote = 1970.01.01 00:00:00, Price = 0.0/0.0
01:24:57 3 EURUSDm,H1: gdt_Quote = 2014.09.03 21:24:57, Price = 1.31461/1.3148
01:24:57 3 EURUSDm,H1: uninit reason 0
01:24:57 Script 3 EURUSDm,H1: removed

Eine statische Methode singleton() erzeugt eine statische Variable des Typs Symbol_Properties, aber zur Kompilierungszeit wird ein NICHT gültiger Standardkonstruktoraufruf-Zugriffsfehler erzeugt, da die Methode, obwohl statisch, - Zugriff auf alle Mitglieder hat, einschließlich private. Daher musste dieser Konstruktor aufgrund eines Fehlers in der MQL4++-Implementierung in public platziert werden. Wenn sie es in Ordnung bringen, müssen wir es nicht mehr tun.

Das Ergebnis der Ausführung zeigt, dass sich die Daten nach dem Aufruf von change() geändert haben. Dies zeigt indirekt an, dass die Funktion change() die Adresse desselben Objekts in sich selbst empfangen hat, die auch in OnStart() empfangen wurde.

Aufgrund des Fehlers in MQL4++ ist dies überhaupt kein Singleton, da der Standardkonstruktor öffentlich ist, so dass viele solcher Objekte erstellt werden können. Wenn der Fehler behoben ist und der Standardkonstruktor im privaten Bereich platziert ist, wird er zu einer vollwertigen Implementierung von Myers' Singleton in MQL4++.

 
ALXIMIKS:

Sie haben in zwei Tagen noch nicht herausgefunden, dass sich Statik in der Struktur und im Unterricht unterschiedlich verhält?

die Strukturen scheinen von C übernommen und nur ein wenig aufgepumpt zu sein, was die Vererbung angeht,

Was den Unterricht betrifft, so ist er vollwertig.

Aus diesem Grund müssen Sie keinen Platz für eine statische Variable in Strukturen reservieren

aber Sie müssen einen Platz im Unterricht reservieren, sonst geht das nicht:

Nicht wahr, dieser wunderbare MQL4++ Compiler verhält sich anders. Sobald Sie eine Objektinstanz erstellen, "richtet" sich das Verhalten aus:

#property strict

/******************************************************************************/
struct A {
  static int x;
};

/******************************************************************************/
void OnStart() {
  A y;
}

Aus irgendeinem Grund lässt es sich nicht kompilieren (die erste und dritte sind Warnungen, aber die zweite ist ein vollwertiger Fehler):

struct has no members, size assigned to 1 byte
unresolved static variable 'A::x'
variable 'y' not used

Ist es also notwendig, in Strukturen "Platz für eine statische Variable" zu reservieren?

Und in der nächsten Version des Terminals/Compilers, wird es die gleiche sein (gut, um nicht zu beeilen, um alles zu beheben, bevor geschrieben, wenn die Version ändern)?

 
TheXpert:

Ich habe die Verkapselung vergessen. Und sie kann gelöscht werden. Und hier gibt es keine ständigen Hinweise). Und im Allgemeinen ist Singleton nicht das beste Muster.

Und Vorlagen sind gut, zumindest einige. Für Klassen, wahrscheinlich nur ein Traum.



Nun, ob es das schlechteste oder das beste ist, will ich nicht beurteilen.

Ich möchte die Diskussionsteilnehmer daran erinnern, dass die oben erwähnten Speicherverwaltungsmodi - automatisch, dynamisch, statisch, basiert - nicht für Vorlagen gelten, egal wie mächtig OOP ist.

 
Так обязательно ли резервировать в структурах "место под static-переменную"?
"Ja", das ist nur ein Hinweis darauf, dass man auch "Nein" sagen kann, aber man sollte es nicht auf diese Weise tun.
 
simpleton:


Wegen eines Fehlers in MQL4++ ist dies kein Singleton, da viele solcher Objekte erstellt werden können, da der Standardkonstruktor öffentlich ist. Wenn der Fehler behoben ist und der Standardkonstruktor im privaten Bereich platziert wird, wird er zu einer vollwertigen Singleton-Implementierung in MQL4++.


Danke, ich wusste nicht, dass ich hier einen Zeiger nehmen kann.

Der Code ist chaotisch, er könnte einfacher sein, leider gibt es keine Vorlagen.

Ich kann den Code nicht einfügen ((

Klasse Singleton{

privat:

class SomeClass{

öffentlich:

int a;

};

Singleton(){}

~Singleton(){}

öffentlich:

static SomeClass* Instance(){

static SomeClass a();

return GetPointer (a);

}

};

void OnStart()

{

SomeClass* some_ptr = Singleton::Instance();

some_ptr.a = 5;

Alert(some_ptr.a);

}

 
ALXIMIKS:


Danke, ich wusste nicht, dass man hier einen Zeiger aufnehmen kann.

Du bringst den Code durcheinander, es könnte einfacher sein, leider gibt es keine Vorlagen.

Ich bekomme den Code nicht zum Laufen ((

Klasse Singleton{

privat:

class SomeClass{

öffentlich:

int a;

};

Singleton(){}

~Singleton(){}

öffentlich:

static SomeClass* Instance(){

static SomeClass a();

return GetPointer (a);

}

};

void OnStart()

{

SomeClass* some_ptr = Singleton::Instance();

some_ptr.a = 5;

Alert(some_ptr.a);

}

Hier ist Myers' Code für C++:

class Singleton
{
private:
    Singleton() {}
    Singleton( const Singleton&);
    Singleton& operator=( Singleton& );
public:
    static Singleton& getInstance() {
        static Singleton  instance;
        return instance;
    }
};

Und hier ist derselbe Code in MQL4++ umgesetzt, was den technischen Teil der Klasse im Beispiel darstellt:

class Symbol_Properties {
private:
   // Реализация технической части singleton'а
  /******************************************************************************/
public: // Вечно в этом MQL4++ что-то не работает: 'Symbol_Properties::Symbol_Prope…' - cannot call private member function
  Symbol_Properties() {};
private: // Восстанавливаем private
  Symbol_Properties(const Symbol_Properties &p);
  void operator =(const Symbol_Properties &);

public:
  static Symbol_Properties *singleton() {
    static Symbol_Properties sp;
    return GetPointer(sp);
  }

Wo ist hier die "Zauberei"?

Ihr Beispiel nutzt Fehler des MQL4++-Compilers aus, insbesondere ist die Verwendung des Typs SomeClass in OnStart() unangemessen, da dies ein verschachtelter Typ der Klasse Singleton ist und der "erwachsene" Compiler sofort einen Fehler erkennt:

try.cpp:33:9: error: unknown type name 'SomeClass'
        SomeClass* some_ptr = Singleton::Instance();
        ^

Dies ist jedoch kein entscheidender Punkt, da ein verschachtelter Typ korrekt angegeben werden kann. Wichtiger ist, dass der SomeClass-Typ im privaten Bereich der Singleton-Klasse deklariert ist, und daher ist die Verwendung von SomeClass in OnStart() nun grundsätzlich falsch, was der "erwachsene" Compiler sofort meldet:

try.cpp:33:20: error: 'SomeClass' is a private member of 'Singleton'
        Singleton::SomeClass* some_ptr = Singleton::Instance();
                   ^

Ihre Implementierung wird funktionieren, es sei denn, der MQL4++-Compiler behebt die Zugriffskontroll-Bacchanalien.

 

1. Maerse, nicht Maerse, was macht das schon, wenn der Code funktioniert und das Richtige ohne Fehler in MQL und nicht in ++ tut.

2. Tut Ihr Code, was er soll? Nein, das tut sie nicht. Sie haben bereits alles verstanden.

Mein Beispiel zeigt die Behandlung von Fehlern (in Bezug auf C++) in MQL. Wenn etwas nicht bequem ist, siehe Punkte 1 und 2.

4. Was die Erstellung eines Zeigers auf eine private Klasse, ja, es ist ein MQL-Fehler, aber es gibt kein Auto, um den Typ zu identifizieren, so ist es gut, dass es funktioniert. \

(p.s. Ich habe es vielleicht auf Kosten des Autos übertrieben, ich sollte es überprüfen)

5. Ich habe in MQL keine Möglichkeit gefunden, einen Zeiger zu derefenzieren, um ein Objekt zu erhalten, daher halte ich den privaten Kopierkonstruktor und den Zuweisungsoperator für überflüssig.

Versuchen Sie, sie zu verwenden, werde ich glücklich sein, den Weg zu sehen))

 
ALXIMIKS:

1. Maerse, nicht Maerse, was soll's, wenn der Code funktioniert und das Richtige tut , ohne Fehler in MQL, nicht in ++.

2. Tut Ihr Code, was er soll? Nein, das tut sie nicht. Sie haben bereits alles verstanden.

Mein Beispiel zeigt die Behandlung von Fehlern (in Bezug auf C++) in MQL. Wenn etwas nicht bequem ist, siehe Punkte 1 und 2.

4. Was die Erstellung eines Zeigers auf eine private Klasse, ja, es ist ein MQL-Fehler, aber es gibt kein Auto, um den Typ zu identifizieren, so ist es gut, dass es funktioniert. \

(p.s. Ich habe es vielleicht auf Kosten des Autos übertrieben, ich sollte es überprüfen)

5. Ich habe in MQL keine Möglichkeit gefunden, einen Zeiger zu derefenzieren, um ein Objekt zu erhalten, daher halte ich den privaten Kopierkonstruktor und den Zuweisungsoperator für überflüssig.

Versuchen Sie, sie zu verwenden, werde ich glücklich sein, den Weg zu sehen))

1. Nun - sie tut es, aber NICHT auf die Art und Weise (Erklärung unten).

2. Wenn sie es nicht in Ordnung bringen, wird es auch nicht funktionieren. Und es ist unwahrscheinlich, dass sie überhaupt umgesetzt werden können.

3. es ist keine Umgehung von Fehlern, es ist Ausbeutung.

4. Es gibt vieles, was nicht da ist.

5. Solche Dinge können in dieser Version möglich sein, insbesondere glaube ich, dass ich geflasht habe, dass der Kopierkonstruktor nicht synthetisiert wird, aber das garantiert nicht, dass er nicht in zukünftigen Versionen synthetisiert wird. Der Aufwand, der mit der Anmeldung verbunden ist, ist dagegen meiner Meinung nach zu vernachlässigen.

Nun, um zu erklären, warum Ihr Code nicht nur die potenziellen Probleme hat, die ich im vorherigen Beitrag erwähnt habe, sondern auch, warum er im Prinzip kein Singleton ist und auch nicht sein wird, und ob sie die Zugriffs-Bacchanalien beheben oder nicht:

#property strict

class Singleton{
private:
         class SomeClass{
         public:
            int a;
         };
        Singleton(){}
        ~Singleton(){}   
public:
        static SomeClass* Instance(){
                        static SomeClass a;
                        return GetPointer (a);
                }
        };
        int i;

void OnStart()
{       
        SomeClass* some_ptr = Singleton::Instance();
        SomeClass obj1;
        SomeClass obj2;

        obj1.a = 3;
        obj2.a = 7;

        some_ptr.a = 5;
        Print("some_ptr.a = ", some_ptr.a);          
        Print("obj1.a = ", obj1.a);          
        Print("obj2.a = ", obj2.a);          
}

Dieser Code wird recht erfolgreich ausgeführt:

10:09:27 Script 3 EURUSDm,H1: loaded successfully
10:09:27 3 EURUSDm,H1: initialized
10:09:27 3 EURUSDm,H1: some_ptr.a = 5
10:09:27 3 EURUSDm,H1: obj1.a = 3
10:09:27 3 EURUSDm,H1: obj2.a = 7
10:09:27 3 EURUSDm,H1: uninit reason 0
10:09:27 Script 3 EURUSDm,H1: removed

Sehen Sie, wie viele Singleton's es geschafft haben, erstellt zu werden, während sie EINMAL existieren?

Würde sich in dieser Hinsicht etwas für Ihren Code ändern, wenn das Zugangsbacchanal behoben wäre?

Wird sich das in meinem Code ändern?

Glauben Sie, dass Ihr Standpunkt umso richtiger wird, je unverblümter Sie ihn vertreten?

 

Ja, danke für Ihre Aufmerksamkeit, Sie haben Recht, es ist auch in dieser Variante kein Singleton.

Über implizite Konstruktoren und Operatoren - machen Sie sie explizit und versuchen Sie, sie zu verwenden, es scheint mir, dass sie nicht funktionieren werden, da man einen Zeiger auf ein Objekt nicht derefenzieren kann

Warum funktioniert es nicht, 'ptr' - kann keine geschützte Mitgliedsfunktion aufrufen :

class smart_ptr{
            Singleton* ptr;
      public:        
            smart_ptr(Singleton* val): ptr(val){}          
            smart_ptr(): ptr(NULL){} 
            ~smart_ptr(){delete ptr;}
      };
 
ALXIMIKS:

Ja, danke für Ihre Aufmerksamkeit, Sie haben Recht, es ist auch in dieser Variante kein Singleton.

Was implizite Konstruktoren und Operatoren betrifft - machen Sie sie explizit und versuchen Sie, sie zu verwenden, es scheint mir, dass sie nicht funktionieren werden, weil es unmöglich ist, den Zeiger auf das Objekt zu derefenzieren

Warum funktioniert es nicht, 'ptr' - kann keine geschützte Mitgliedsfunktion aufrufen :

Es scheint nicht zu funktionieren und es gibt noch viele weitere Fehler. Es ist schade, dass das nur sehr wenige Menschen bemerken. Ich möchte keinen Streit anfangen, aber es gibt tatsächlich einen großen Unterschied. Einige Dinge, die für Strukturen in C++ gelten, funktionieren in MKL4 nicht. Aber ich werde schweigen... sonst werden sie anfangen, Fragen zu stellen wie:

"Warum brauche ich es".

Wenn auch nur, damit ich nicht in ein unfertiges Lehrbuch einsteigen kann, sondern einfach Dinge, die in C++ funktionieren, in MKL4 schreibe und nicht darüber nachdenke, ob sie hier funktionieren oder nicht. Mehr brauche ich in diesem Stadium nicht...

Grund der Beschwerde: