English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
MQL5'te Nesne Yaratma ve Yok Etme

MQL5'te Nesne Yaratma ve Yok Etme

MetaTrader 5Örnekler | 9 Aralık 2021, 10:20
63 0
MetaQuotes
MetaQuotes

Bu makale ne hakkındadır?

MQL5 programları, Nesne Yönelimli Programlama (OOP) kavramlarıyla yazılmıştır ve bu, yalnızca özel kitaplıklar oluşturmak için yeni olanaklar açmakla kalmaz, aynı zamanda diğer geliştiricilerin eksiksiz ve test edilmiş sınıflarını kullanabilmenizi de sağlar. MetaTrader 5 Müşteri Terminali'nin içerdiği Standart Kitaplıkta, binlerce yöntemi içeren yüzlerce sınıf vardır.

OOP'nin tüm avantajlarından yararlanmak için MQL5 programlarında nesne oluşturma ve silme ile ilgili bazı ayrıntıları netleştirmemiz gerekir. Nesne Oluşturma ve Silme, Belgeler bölümünde kısaca açıklanmıştır ve bu makale bu konuyu örneklerle açıklayacaktır.

Global Değişkenlerin Başlatılması ve Sonlandırılması

Global değişkenlerin başlatılması, MQL5 programı çalıştırıldıktan hemen sonra ve herhangi bir fonksiyon çağrısından önce yapılır. Başlatma sırasında, ilk değerler basit tiplerin değişkenlerine atanır ve bunlar içinde bildirilmişse nesnelerin yapıcısı çağrılır. 

Örnek olarak, CObjectA ve CObjectB olmak üzere iki sınıf tanımlayalım. Her sınıfın basit Print() fonksiyonunu içeren bir yapıcısı ve yıkıcısı vardır. Bu sınıf tiplerinin değişkenlerini global olarak tanımlayalım ve betiği çalıştıralım.

//+------------------------------------------------------------------+
//|                                         GlobalVar_TestScript.mq5 |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
class CObjectA
  {
public:
                     CObjectA(){Print(__FUNCTION__," Constructor");}
                    ~CObjectA(){Print(__FUNCTION__," Destructor");}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CObjectB
  {
public:
                     CObjectB(){Print(__FUNCTION__," Constructor");}
                    ~CObjectB(){Print(__FUNCTION__," Destructor");}
  };
//--- declaring the objects globally
CObjectA first;
CObjectB second;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   Print(__FUNCTION__);
  }

Betik sonucu, Uzman günlüğünde gösterilir:

GlobalVar_TestScript (EURUSD,H1)    13:05:07    CObjectA::ObjectA  Constructor
GlobalVar_TestScript (EURUSD,H1)    13:05:07    CObjectB::ObjectB  Constructor
GlobalVar_TestScript (EURUSD,H1)    13:05:07    OnStart
GlobalVar_TestScript (EURUSD,H1)    13:05:07    CObjectB::~ObjectB  Destructor
GlobalVar_TestScript (EURUSD,H1)    13:05:07    CObjectA::~ObjectA  Destructor

Günlükten açıkça anlaşılacağı üzere, başlatma sırası GlobalVar_TestScript.mq5 betiğindeki değişkenlerin bildirim sırasına uygundur ve sonlandırma işlemi MQL5 programı kullanıma alınmadan önce ters sırada yapılmıştır.

Yerel Değişkenlerin Başlatılması ve Sonlandırılması

Yerel değişkenler bildirildikleri program blokunun bitiminde, bildirim sıralarının tersine göre sonlandırılır. Program bloğu, anahtar operatörünün, döngü operatörlerinin (while ve do-while için), fonksiyon gövdesinin veya if-else operatörünün bir parçası olabilen bileşik bir operatördür.

Yerel değişkenler, yalnızca programda kullanılıyorlarsa başlatılır. Bir değişken bildirilmişse, ancak bildirildiği kod bloğu yürütülmemişse, bu değişken oluşturulmaz ve bu nedenle başlatılmaz. 

Bunu göstermek için CObjectA ve CObjectB sınıflarımıza geri dönelim ve yeni CObjectС sınıfını oluşturalım. Sınıflar hala global olarak bildirilir, ancak bu sınıfların değişkenleri artık OnStart() fonksiyonunda yerel olarak bildirilir.

Şimdi CObjectA sınıfının değişkenini fonksiyonun ilk satırında açık bir şekilde bildirelim, ancak CObjectB ve CObjectС sınıflarının nesneleri ayrı bloklarda bildirilecek ve bu, yürütme girdi değişkeninin değerine bağlı olarak yürütülecektir. MetaEditor'da MQL5 programlarının girdi değişkenleri kahverengi ile vurgulanmıştır.

//+------------------------------------------------------------------+
//|                                          LocalVar_TestScript.mq5 |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property script_show_inputs
//--- input parameters
input bool     execute=false;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CObjectA
  {
public:
                     CObjectA(){Print(__FUNCTION__," Constructor");}
                    ~CObjectA(){Print(__FUNCTION__," Destructor");}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CObjectB
  {
public:
                     CObjectB(){Print(__FUNCTION__," Constructor");}
                    ~CObjectB(){Print(__FUNCTION__," Destructor");}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CObjectC
  {
public:
                     CObjectC(){Print(__FUNCTION__," Constructor");}
                    ~CObjectC(){Print(__FUNCTION__," Destructor");}
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CObjectA objA;
//--- this block will NOT be executed if execute==false
   if(execute)
     {
      CObjectB objB;
     }
//--- this block WILL be executed if execute==false
   if(!execute)
     {
      CObjectC objC;
     }
  }
//+------------------------------------------------------------------+

Sonuç:

LocalVar_TestScript (GBPUSD,H1)    18:29:00    CObjectA::CObjectA  Constructor
LocalVar_TestScript (GBPUSD,H1)    18:29:00    CObjectC::CObjectC  Constructor
LocalVar_TestScript (GBPUSD,H1)    18:29:00    CObjectC::~CObjectC  Destructor
LocalVar_TestScript (GBPUSD,H1)    18:29:00    CObjectA::~CObjectA  Destructor

Her zaman CObjectA sınıfının nesnesi, yürütme girdi parametresinin değeri ne olursa olsun,ilk önce otomatik olarak başlatılacaktır. Ardından, objB veya objC nesnesi otomatik olarak başlatılır. Bu, yürütme girdi parametresinin değerine göre hangi bloğun yürütüldüğüne bağlıdır. Varsayılan olarak, bu parametre yanlış değerine sahiptir ve bu durumda objA değişkeninin başlatılmasından sonra objC değişkeninin başlatılması gelir. Bu, yapıcı ve yıkıcının yürütmesinde açıkça görülür.

Ancak, başlatma sırası ne olursa olsun (yürütme parametresinden bağımsız olarak), karmaşık türdeki değişkenlerin sonlandırma işlemi, başlatma sırasının tersinde yapılır. Bu, hem yerel hem de otomatik olarak oluşturulan global sınıf nesneleri için geçerlidir. Bu durumda aralarında bir fark yoktur.

Dinamik Olarak Oluşturulan Nesnelerin Başlatılması ve Sonlandırılması

MQL5'te bileşik nesneler otomatik olarak başlatılır, ancak nesne oluşturma sürecini elle kontrol etmek istiyorsanız nesne işaretçilerini kullanmalısınız. Bir sınıfın nesne işaretçisi olarak bildirilen bir değişken, nesnenin kendisini içermez ve bu nesnenin otomatik olarak başlatılması söz konusu değildir.

İşaretçiler yerel ve/veya genel olarak bildirilebilir ve aynı zamanda devralınan tipin NULL ile boş değeri başlatılabilirler. Nesne oluşturma, yalnızca nesne işaretçisine yeni operatör uygulandığında yapılır ve nesne işaretçisi bildirimine bağlı değildir.

Dinamik olarak oluşturulan nesneler, silme operatörü kullanılarak silinir, bu yüzden bunu ele almalıyız. Örnek olarak, global olarak iki değişken tanımlayalım: Biri CObjectA tipinden ve biri de CObjectB tipinden olsun; bir diğeri de nesne işaretçisi ile CObjectC tipinden başka bir değişken olsun.

//+------------------------------------------------------------------+
//|                                       GlobalVar_TestScript_2.mq5 |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
class CObjectA
  {
public:
                     CObjectA(){Print(__FUNCTION__," Constructor");}
                    ~CObjectA(){Print(__FUNCTION__," Destructor");}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CObjectB
  {
public:
                     CObjectB(){Print(__FUNCTION__," Constructor");}
                    ~CObjectB(){Print(__FUNCTION__," Destructor");}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CObjectC
  {
public:
                     CObjectC(){Print(__FUNCTION__," Constructor");}
                    ~CObjectC(){Print(__FUNCTION__," Destructor");}
  };
CObjectC *pObjectC;
CObjectA first;
CObjectB second;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   pObjectC=new CObjectC;
   Print(__FUNCTION__);
   delete(pObjectC);
  }
//+------------------------------------------------------------------+

Dinamik olarak oluşturulan nesne işaretçisi pObjectC, birinci ve ikinci statik değişkenlerden önce bildirilmiş olsa da, bu nesne yalnızca yeni operatör tarafından oluşturulduğunda başlatılır. Bu örnekte, yeni operatör OnStart() fonksiyonunun içindedir.

GlobalVar_TestScript_2 (EURUSD,H1)    15:03:21    CObjectA::CObjectA  Constructor
GlobalVar_TestScript_2 (EURUSD,H1)    15:03:21    CObjectB::CObjectB  Constructor
GlobalVar_TestScript_2 (EURUSD,H1)    15:03:21    CObjectC::CObjectC  Constructor
GlobalVar_TestScript_2 (EURUSD,H1)    15:03:21    OnStart
GlobalVar_TestScript_2 (EURUSD,H1)    15:03:21    CObjectC::~CObjectC  Destructor
GlobalVar_TestScript_2 (EURUSD,H1)    15:03:21    CObjectB::~CObjectB  Destructor
GlobalVar_TestScript_2 (EURUSD,H1)    15:03:21    CObjectA::~CObjectA  Destructor

OnStart() fonksiyonundaki program yürütmesi operatöre ulaştığında

   pObjectC=new CObjectC;

nesne başlatılır ve bu nesnenin yapıcısı çağrılır. Sonra program bu dizgiyi yürütür

   Print(__FUNCTION__);

bu, Journal'da aşağıdaki metni verir:

GlobalVar_TestScript_2 (EURUSD,H1)    15:03:21    OnStart

ardından dinamik olarak oluşturulan nesne, silme operatörü çağrılarak silinir:

   delete(pObjectC);

Yani nesneler yeni operatör tarafından oluşturulurken dinamik olarak başlatılır ve silme operatörü tarafından silinir. 

Zorunlu durum: object_pointer=new Class_Name ifadesi kullanılarak oluşturulan tüm nesneler, her zaman delete(object_pointer) operatörü kullanılarak silinmelidir. Dinamik olarak oluşturulan nesne (başlatıldığı bloğun sonundan sonra) herhangi bir nedenle silme operatörü kullanılarak silinmediyse, Uzman günlüğünde ilgili bir mesaj gösterilecektir.


Dinamik Olarak Oluşturulmuş Nesneleri Silme

Daha önce bahsedildiği gibi, dinamik olarak oluşturulan her nesne yeni operatör kullanılarak başlatılır ve her zaman silme operatörü kullanılarak silinmelidir. Ancak, yeni operatörün bir nesne oluşturduğunu ve bir işaretçiyi o nesneye döndürdüğünü unutmayın.  Oluşturulan nesnenin kendisi, nesne işaretçisini içeren değişkende değildir. Birkaç işaretçi bildirebilir ve bunları aynı nesne işaretçisine atayabilirsiniz.

//+------------------------------------------------------------------+
//|                                        LocalVar_TestScript_1.mq5 |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//|  simple class                                                    |
//+------------------------------------------------------------------+
class CItem
  {
public:
                     CItem(){Print(__FUNCTION__," Constructor");}
                    ~CItem(){Print(__FUNCTION__," Destructor");}
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- declaring the first object pointer array 
   CItem* array1[5];
//--- declaring the first object pointer array 
   CItem* array2[5];
//--- filling arrays in the loop
   for(int i=0;i<5;i++)
     {
      //--- creating a pointer for the first array using new operator
      array1[i]=new CItem;
      //--- creating a pointer for the second array via copy from the first array
      array2[i]=array1[i];
     }
   // We "forgot" to delete objects before exiting the function. See "Experts" tab.
  }
//+------------------------------------------------------------------+

Çıktı, birkaç silinmemiş nesne kaldığını söylüyor. Ancak, yeni operatör yalnızca 5 nesne oluşturduğu için, düşündüğünüz gibi, 10 yerine yalnızca 5 silinmemiş nesne olacaktır.

(GBPUSD,H1)    12:14:04    CItem::CItem  Constructor
(GBPUSD,H1)    12:14:04    CItem::CItem  Constructor
(GBPUSD,H1)    12:14:04    CItem::CItem  Constructor
(GBPUSD,H1)    12:14:04    CItem::CItem  Constructor
(GBPUSD,H1)    12:14:04    CItem::CItem  Constructor
(GBPUSD,H1)    12:14:04    5 silinmemiş nesne kaldı

Dinamik olarak oluşturulan nesne için yıkıcı çağrılmasa bile (nesne, silme operatörü kullanılarak silinmez), bellek yine de temizlenecektir. Ancak "Uzmanlar" günlüğünde nesnenin silinmediği söyleniyor. Bu, uygun olmayan nesne yönetimini tespit etmenize ve hatayı düzeltmenize yardımcı olabilir.

Bir sonraki örnekte, iki işaretçi dizisinin her birindeki işaretçileri silmeye çalışalım: array1 ve array2.

//+------------------------------------------------------------------+
//|                                        LocalVar_TestScript_2.mq5 |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//|  simple class                                                   |
//+------------------------------------------------------------------+
class CItem
  {
public:
                     CItem(){Print(__FUNCTION__," Constructor");}
                    ~CItem(){Print(__FUNCTION__," Destructor");}
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- declaring the first object pointer array
   CItem* array1[5];
//--- declaring the second object pointer array
   CItem* array2[5];
//--- filling arrays in the loop
   for(int i=0;i<5;i++)
     {
      //--- creating a pointer for the first array using new operator
      array1[i]=new CItem;
      //--- creating a pointer for the second array via copy from the first array
      array2[i]=array1[i];
     }
//--- deleting object using pointers of second array
   for(int i=0;i<5;i++) delete(array2[i]);
//--- let's try to delete objects using pointers of first array
   for(int i=0;i<5;i++) delete(array2[i]);
// in Experts tab there are messages about trying to delete invalid pointer
  }
//+------------------------------------------------------------------+

Uzmanlar sekmesindeki sonuç artık farklı.

(GBPUSD,H1)    15:02:48    CItem::CItem  Constructor
(GBPUSD,H1)    15:02:48    CItem::CItem  Constructor
(GBPUSD,H1)    15:02:48    CItem::CItem  Constructor
(GBPUSD,H1)    15:02:48    CItem::CItem  Constructor
(GBPUSD,H1)    15:02:48    CItem::CItem  Constructor
(GBPUSD,H1)    15:02:48    CItem::~CItem  Destructor
(GBPUSD,H1)    15:02:48    CItem::~CItem  Destructor
(GBPUSD,H1)    15:02:48    CItem::~CItem  Destructor
(GBPUSD,H1)    15:02:48    CItem::~CItem  Destructor
(GBPUSD,H1)    15:02:48    CItem::~CItem  Destructor
(GBPUSD,H1) 15:02:48 geçersiz işaretçiyi sil
(GBPUSD,H1) 15:02:48 geçersiz işaretçiyi sil
(GBPUSD,H1) 15:02:48 geçersiz işaretçiyi sil
(GBPUSD,H1) 15:02:48 geçersiz işaretçiyi sil
(GBPUSD,H1) 15:02:48 geçersiz işaretçiyi sil

CItem tarafından oluşturulan nesneler ilk for() döngüsünde başarıyla silinmiştir ancak ikinci döngüde var olmayan nesneleri silmeye yönelik başka girişimler, geçersiz işaretçilere dair bazı mesajlara neden olmuştur. Dinamik olarak oluşturulan nesne bir kez silinmeli ve herhangi bir nesne işaretçisi kullanılmadan önce CheckPointer() fonksiyonu ile kontrol edilmelidir.

CheckPointer() fonksiyonu ile işaretçi denetimi

CheckPointer(), işaretçileri kontrol etmek için kullanılır ve işaretçi tipini tanımlamaya yarar. Dinamik olarak oluşturulmuş nesnelerle çalışırken iki olası durum vardır: 

  • yürütme bloğunun sonunda silmeyi geri alma
  • zaten silinmiş nesneyi silme girişimi 

Nesnelerin karşılıklı ilişkilerini gösteren başka bir örneğe bakalım. İki sınıf oluşturalım: Birinci sınıf CItemArray, başka bir CItem sınıfının işaretçi dizisini içerir.

//+------------------------------------------------------------------+
//|                                        LocalVar_TestScript_3.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//|  simple class                                                    |
//+------------------------------------------------------------------+
class CItem
  {
public:
                     CItem(){Print(__FUNCTION__," Constructor");}
                    ~CItem(){Print(__FUNCTION__," Destructor");}
  };
//+------------------------------------------------------------------+
//| class, containing pointer array of CItem class                   |
//+------------------------------------------------------------------+
class CItemArray
  {
private:
   CItem            *m_array[];
public:
                     CItemArray(){Print(__FUNCTION__," Constructor");}
                    ~CItemArray(){Print(__FUNCTION__," Destructor");Destroy();}
   void               SetArray(CItem &array[]);
protected:
   void               Destroy();
  };
//+------------------------------------------------------------------+
//|  filling pointers array                                          |
//+------------------------------------------------------------------+
CItemArray::SetArray(CItem &array[])
  {
   int size=ArraySize(array);
   ArrayResize(m_array,size);
   for(int i=0;i<size;i++)m_array[i]=GetPointer(array[i]);
  }
//+------------------------------------------------------------------+
//|  releasing                                                       |
//+------------------------------------------------------------------+
CItemArray::Destroy(void)
  {
   for(int i=0;i<ArraySize(m_array);i++)
     {
      if(CheckPointer(m_array[i])!=POINTER_INVALID)
        {
         if(CheckPointer(m_array[i])==POINTER_DYNAMIC) delete(m_array[i]);
        }
      else Print("Invalid pointer to delete");
     }
  }

Sınıflar bizzat herhangi bir hata içermez, ancak kullanımları sürprizlere açık olabilir. Betiğin ilk varyantı:

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CItemArray items_array;
   CItem array[5];
   items_array.SetArray(array);
  }

Bu betik varyantını çalıştırmak aşağıdaki mesajları görüntüler:

(GBPUSD,H1)    16:06:17    CItemArray::CItemArray  Constructor
(GBPUSD,H1)    16:06:17    CItem::CItem  Constructor
(GBPUSD,H1)    16:06:17    CItem::CItem  Constructor
(GBPUSD,H1)    16:06:17    CItem::CItem  Constructor
(GBPUSD,H1)    16:06:17    CItem::CItem  Constructor
(GBPUSD,H1)    16:06:17    CItem::CItem  Constructor
(GBPUSD,H1)    16:06:17    CItem::~CItem  Destructor
(GBPUSD,H1)    16:06:17    CItem::~CItem  Destructor
(GBPUSD,H1)    16:06:17    CItem::~CItem  Destructor
(GBPUSD,H1)    16:06:17    CItem::~CItem  Destructor
(GBPUSD,H1)    16:06:17    CItem::~CItem  Destructor
(GBPUSD,H1)    16:06:17    CItemArray::~CItemArray  Destructor
(GBPUSD,H1)    16:06:17    Silinmek için geçersiz işaretçi
(GBPUSD,H1)    16:06:17    Silinmek için geçersiz işaretçi
(GBPUSD,H1)    16:06:17    Silinmek için geçersiz işaretçi
(GBPUSD,H1)    16:06:17    Silinmek için geçersiz işaretçi

CItemArray sınıf değişkeninin bildirimi önce geldiğinden, ilk olarak o başlatılır ve sınıf yıkıcı çağrılır. Ardından, CItem class nesne işaretçilerini içeren array[5] bildirilir. Bu yüzden her nesnenin başlatılmasıyla ilgili beş mesaj görürüz.

Bu basit betiğin son satırında, array[5] dizisindeki işaretçiler, items_array adlı dahili nesne işaretçileri dizisine kopyalanır (Bkz. 'LocalVar_TestScript_4.mq5').

   items_array.SetArray(array);

Betik, şimdilik yürütmeyi durdurur ve otomatik olarak oluşturulan nesneler otomatik olarak silinir. Silinecek ilk nesne, en son başlatılan nesnedir. Bu, array[5] işaretçiler dizisidir. CItem sınıf yıkıcısının çağrılmasıyla ilgili beş Günlük kaydı bunu doğrulamaktadır. Ardından, array[5] değişkeninden hemen önce başlatılması sebebiyle, items_array nesnesi için yıkıcının çağrılmasıyla ilgili mesaj gelir. 

Ancak, CArrayItem sınıf yıkıcısı, silme operatörü üzerinden m_array[] içindeki işaretçiler aracılığıyla CItem nesnelerini silmeye çalışan korumalı Destroy() fonksiyonunu çağırır. Önce işaretçi kontrol edilir ve geçersizse nesneler silinmez ve "Silmek için geçersiz işaretçi" mesajı görüntülenir. 

Günlükte bu türden 5 kayıt vardır, yani m_array[] dizisindeki tüm işaretçiler geçersizdir. Bunun nedeni, bu işaretçilerin nesnelerinin array[] dizisinin sonlandırılması sırasında zaten sonlandırılmış olmasıdır.

Şimdi Item_array ve items_array[] değişkenlerinin bildirimlerini değiştirerek betiğimizde ince ayar yapalım.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CItem array[5];
   CItemArray items_array;
   items_array.SetArray(array);
  }

Düzeltilmiş betik hata üretmez. En son bildirildiği için, ilk olarak items_array değişkeni sonlandırıldı. Sonlandırma işlemi sırasında ~CItemArray() sınıfı yıkıcısı çağrıldı, bu da Destroy() fonksiyonunu çağırdı. 

Bu bildirim sırasında, items_array, array[5] dizisinden önce silinir. item_array yıkıcısından çağrılan Destroy() fonksiyonunda, işaretçi nesneleri hala mevcuttur, dolayısıyla hiçbir hata oluşmaz.

Dinamik olarak oluşturulan nesnelerin doğru silinmesi GetPointer() fonksiyonu örneğinde de görülebilir. Bu örnekte, nesnelerin silinmesinin doğru sırasını sağlamak için Destroy() fonksiyonu açıkça çağrılır.

Sonuç

Gördüğünüz gibi, nesnelerin oluşturulması ve silinmesi basit bir şekilde yapılır. Bu makaledeki tüm örnekleri gözden geçirerek otomatik ve dinamik olarak oluşturulan nesneler arasında kendi karşılıklı ilişki varyantlarınızı oluşturabilirsiniz.

Nesnelerin doğru silinmesi için her zaman sınıflarınızı kontrol etmeli ve yıkıcılarınızı doğru şekilde tasarlamalısınız, böylece geçersiz işaretçilere erişirken hata oluşmaz. Yeni operatör kullanılarak dinamik olarak oluşturulan nesneleri kullanırsanız, bu nesneleri silme operatörünü kullanarak doğru şekilde silmeniz gerektiğini unutmayın.

Bu makaleden, yalnızca MQL5'te nesne oluşturma ve silme sırasını öğrendiniz. Nesne işaretçileriyle güvenli bir çalışma düzenleme konusu ise bu makalenin kapsamını aşmaktadır.

MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/28

Yeni Başlayanlar için MQL5: Uzman Danışmanlarda Teknik Göstergeleri Kullanma Rehberi Yeni Başlayanlar için MQL5: Uzman Danışmanlarda Teknik Göstergeleri Kullanma Rehberi
Bir Uzman Danışmanda yerleşik veya özel bir göstergenin değerlerini elde etmek için, öncelikle ilgili işlev kullanılarak tanıtıcı değeri oluşturulmalıdır. Makaledeki örnekler, kendi programlarınızı oluştururken teknik göstergelerin nasıl kullanılacağını gösterir. Bu makale, MQL5 dilinde oluşturulan göstergeleri açıklar. Alım satım stratejileri geliştirme konusunda fazla deneyimi olmayanlar için tasarlanmıştır ve sunulan fonksiyon kitaplığını kullanarak göstergelerle çalışmanın basit ve net yollarını sunar.
Uzman Danışmanlarda Sınırlamalar ve Doğrulamalar Uzman Danışmanlarda Sınırlamalar ve Doğrulamalar
Pazartesi günü bu sembolün alım satımına izin verilir mi? Pozisyon açmak için yeterli para var mı? Zararı Durdur tetiklenirse kayıp ne kadar büyük olur? Bekleyen emirlerin sayısı nasıl sınırlandırılır? Alım satım işlemi mevcut çubukta mı yoksa önceki çubukta mı gerçekleştirildi? Bir alım satım robotu bu tür doğrulamaları gerçekleştiremezse, herhangi bir alım satım stratejisi kaybeden bir stratejiye dönüşebilir. Bu makale, herhangi bir Uzman Danışmanda yararlı olan doğrulama örneklerini gösterir.
MQL5'e Giriş: Basit Uzman Danışman (EA) ve Özel Gösterge nasıl yazılır MQL5'e Giriş: Basit Uzman Danışman (EA) ve Özel Gösterge nasıl yazılır
MetaTrader 5 İstemci Terminaline dahil edilen MetaQuotes Programlama Dili 5 (MQL5), MQL4'e kıyasla birçok yeni imkana ve daha yüksek performansa sahiptir. Bu makale, bu yeni programlama dili hakkında bilgi edinmenize yardımcı olacaktır. Uzman Danışman ve Özel Göstergenin nasıl yazılacağına dair basit örnekler bu makalede sunulmuştur. Bu örnekleri anlamak için gerekli olan MQL5 dilinin bazı ayrıntılarını da ele alacağız.
Bir Göstergenin Diğerine Uygulanması Bir Göstergenin Diğerine Uygulanması
OnCalculate() fonksiyon çağrısının kısa biçimini kullanan bir gösterge yazarken, bir göstergenin yalnızca fiyat verileriyle değil, aynı zamanda başka bir göstergenin verileriyle de hesaplanabileceği gerçeğini kaçırabilirsiniz. Diğer göstergelerin verilerine doğru uygulanması için bir göstergeyi geliştirmek ister misiniz? Bu makalede, bu tür bir değişiklik için gereken tüm adımları gözden geçireceğiz.