Objektanzeiger

MQL5 ermöglicht die dynamische Erzeugung von Objekten komplexen Typs. Dies geschieht mit dem Operator 'new', der einen Deskriptor des erzeugten Objekts zurückgibt. Die Größe des Deskriptors beträgt 8 Bytes. Syntaktisch sind Objektdeskriptoren in MQL5 ähnlich wie C++ Pointer.

Beispiel:

MyObject* hobject= new MyObject();

Im Gegensatz zu C++ ist die Variable "hobject" aus dem obigen Beispiel kein Zeiger auf den Speicher, sondern ein Objektdeskriptor. Außerdem müssen in MQL5 alle Objekte in Funktionsparametern per Referenz übergeben werden. Die folgenden Beispiele zeigen die Übergabe von Objekten als Funktionsparameter:

class Foo
  {
public:
   string            m_name;
   int               m_id;
   static int        s_counter;
   //--- Konstruktor und Destruktor
                     Foo(void){Setup("noname");};
                     Foo(string name){Setup(name);};
                    ~Foo(void){};
   //--- Initialisieren des Objektes Foo
   void              Setup(string name)
     {
      m_name=name;
      s_counter++;
      m_id=s_counter;
     }
  };
int Foo::s_counter=0;
//+------------------------------------------------------------------+
//| Skript Programm Start Funktion                                   |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Deklarieren des Objekts als Variable, mit automatischer Erstellung
   Foo foo1;
//--- Variante der Übergabe eines Objekts per Referenz
   PrintObject(foo1);
 
//--- einen Zeiger auf ein Objekt deklarieren und es mit dem Operator "new" erstellen
   Foo *foo2=new Foo("foo2");
//--- Variante der Übergabe eines Zeigers auf ein Objekt per Referenz
   PrintObject(foo2); // der Zeiger auf das Objekt wird vom Compiler automatisch umgewandelt
 
//--- ein Array von Foo-Objekten deklarieren
   Foo foo_objects[5];
//--- Variante der Übergabe eines Arrays von Objekten
   PrintObjectsArray(foo_objects); // eine separate Funktion zur Übergabe eines Arrays von Objekten
 
//--- ein Array von Zeigern auf Objekte des Typs Foo deklarieren
   Foo *foo_pointers[5];
   for(int i=0;i<5;i++)
      foo_pointers[i]=new Foo("foo_pointer");
//--- ein Array von Zeigern auf Objekte des Typs Foo deklarieren
   PrintPointersArray(foo_pointers); // eine separate Funktion zur Übergabe eines Arrays von Zeigern
 
//--- Löschen vor Beendigung, um sicher die als Zeiger angelegten Objekte zu löschen
   delete(foo2);
//--- das Array der Zeiger entfernen
   int size=ArraySize(foo_pointers);
   for(int i=0;i<5;i++)
      delete(foo_pointers[i]);
//---   
  }
//+------------------------------------------------------------------+
//|  Objekte werden immer als Referenz übergeben                     |
//+------------------------------------------------------------------+
void PrintObject(Foo &object)
  {
   Print(__FUNCTION__,": ",object.m_id," Object name=",object.m_name);
  }
//+------------------------------------------------------------------+
//| Ein Array von Objekten übergeben                                |
//+------------------------------------------------------------------+
void PrintObjectsArray(Foo &objects[])
  {
   int size=ArraySize(objects);
   for(int i=0;i<size;i++)
      PrintObject(objects[i]);
  }
//+------------------------------------------------------------------+
//| Ein Array von Objektpointer übergeben                           |
//+------------------------------------------------------------------+
void PrintPointersArray(Foo* &objects[])
  {
   int size=ArraySize(objects);
   for(int i=0;i<size;i++)
      PrintObject(objects[i]);
  }
//+------------------------------------------------------------------+

 

Prüfen des Zeigers vor der Verwendung

Der Versuch, auf einen ungültigen Zeiger zuzugreifen, führt zum kritischen Herunterfahren des Programms. Die Funktion CheckPointer wird verwendet, um einen Zeiger vor der Verwendung zu prüfen. Der Zeiger kann in den folgenden Fällen ungültig sein:

  • der Zeiger ist gleich NULL;
  • das Objekt wurde mit dem Operator delete zerstört.

Diese Funktion kann verwendet werden, um einen Zeiger zu überprüfen. Ein Wert ungleich Null zeigt an, dass auf Daten an diesem Zeiger zugegriffen werden kann.

class CMyObject
 {
protected:
  double             m_value;
public:
                     CMyObject(void);
                     CMyObject(double value) {m_value=value;};
                    ~CMyObject(void){};
  //---
  double             Value(void) {return(m_value);}
 };
//+------------------------------------------------------------------+
//| Skript Programm Start Funktion                                   |
//+------------------------------------------------------------------+
void OnStart()
 {
//--- ein nicht-initialisiertes Objekt erstellen
  CMyObject *pointer;
  if(CheckPointer(pointer)==POINTER_INVALID)
    Print("1. Pointer ist "EnumToString(CheckPointer(pointer)));
  else
    Print("1. pointer.Value()="pointer.Value());
 
//--- den Zeiger initialisieren
  pointer=new CMyObject(M_PI);
  if(CheckPointer(pointer)==POINTER_INVALID)
    Print("2. Pointer ist "EnumToString(CheckPointer(pointer)));
  else
    Print("2. pointer.Value()="pointer.Value());
 
//--- Löschen des Objekts
  delete(pointer);
  if(CheckPointer(pointer)==POINTER_INVALID)
    Print("3. Pointer ist "EnumToString(CheckPointer(pointer)));
  else
    Print("3. pointer.Value()="pointer.Value());
 }
/*
   1pointer is POINTER_INVALID
   2pointer.Value()=3.141592653589793
   3pointer is POINTER_INVALID
*/

Um den Zeiger schnell zu überprüfen, können Sie auch den Operator "!" (LNOT) verwenden, der ihn durch einen impliziten Aufruf der Funktion CheckPointer überprüft. Dies ermöglicht einen prägnanteren und klareren Code. Nachfolgend sind die Prüfungen aus dem vorherigen Beispiel aufgeführt:

//+------------------------------------------------------------------+
//| Skript Programm Start Funktion                                   |
//+------------------------------------------------------------------+
void OnStart()
 {
//--- ein nicht-initialisiertes Objekt erstellen
  CMyObject *pointer;
  if(!pointer)
    Print("1. Pointer ist "EnumToString(CheckPointer(pointer)));
  else
    Print("1. pointer.Value()="pointer.Value());
 
//--- den Zeiger initialisieren
  pointer=new CMyObject(M_PI);
  if(!pointer)
    Print("2. Pointer ist "EnumToString(CheckPointer(pointer)));
  else
    Print("2. pointer.Value()="pointer.Value());
 
//--- Löschen des Objekts
  delete(pointer);
  if(!pointer)
    Print("3. Pointer ist "EnumToString(CheckPointer(pointer)));
  else
    Print("3. pointer.Value()="pointer.Value());
 }
/*
   1pointer is POINTER_INVALID
   2pointer.Value()=3.141592653589793
   3pointer is POINTER_INVALID
*/

Der Operator "==" wird für eine schnelle Prüfung auf NULL verwendet. Zum Beispiel: ptr==NULL oder ptr!=NULL.

Sehen Sie auch

Variablen, Initialisierung der Variablen, Sichtbereich und Lebensdauer der Variablen, Erzeugung und Entfernung der Objekte