MQL5 は複合型オブジェクトの動的作成を可能にします。これは、作成されたオブジェクトの記述子を返す「new」演算子を使用して行われます。記述子のサイズは8バイトです。構文的に、MQL5のオブジェクト記述子はC++ポインタに似ています。

例:

MyObject* hobject= new MyObject();

C++ とは異なり、上記の例の「hobject」変数はメモリへのポインターではなく、オブジェクト記述子です。さらに、MQL5では、関数パラメータ内のすべてのオブジェクトは参照によって渡される必要があります。以下の例は、オブジェクトを関数パラメータとして渡す方法を示しています。

class Foo
 {
public:
  string            m_name;
  int               m_id;
  static int        s_counter;
  //--- コンストラクタとデストラクタ
                    Foo(void){Setup("noname");};
                    Foo(string name){Setup(name);};
                   ~Foo(void){};
  //--- Fooオブジェクトを初期化する
  void              Setup(string name)
    {
     m_name=name;
     s_counter++;
     m_id=s_counter;
    }
 };
int Foo::s_counter=0;
//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数                                              |
//+------------------------------------------------------------------+
void OnStart()
 {
//--- 自動作成を使用してオブジェクトを変数として宣言する
  Foo foo1;
//--- 参照によってオブジェクトを渡す
  PrintObject(foo1);
 
//--- オブジェクトへのポインタを宣言し「new」演算子を使用して作成する
  Foo *foo2=new Foo("foo2");
//--- 参照によってオブジェクトへのポインタを渡す
  PrintObject(foo2); // the pointer to the object is converted by the compiler automatically
 
//--- Fooオブジェクトの配列を宣言する
  Foo foo_objects[5];
//--- オブジェクトの配列を渡す
  PrintObjectsArray(foo_objects); // a separate function for passing an array of objects
 
//--- Foo 型オブジェクトへのポインタの配列を宣言する
  Foo *foo_pointers[5];
  for(int i=0;i<5;i++)
     foo_pointers[i]=new Foo("foo_pointer");
//--- ポインタの配列を渡す
  PrintPointersArray(foo_pointers); // a separate function for passing an array of pointers
 
//--- 終了する前に、ポインタとして作成されたオブジェクトを必ず削除する
  delete(foo2);
//--- ポインタ配列を削除する
  int size=ArraySize(foo_pointers);
  for(int i=0;i<5;i++)
    delete(foo_pointers[i]);
//---  
 }
//+------------------------------------------------------------------+
//| オブジェクトは常に参照によって渡される                                       |
//+------------------------------------------------------------------+
void PrintObject(Foo &object)
 {
  Print(__FUNCTION__,": ",object.m_id," Object name=",object.m_name);
 }
//+------------------------------------------------------------------+
//| オブジェクトの配列を渡す                                                |
//+------------------------------------------------------------------+
void PrintObjectsArray(Foo &objects[])
 {
  int size=ArraySize(objects);
  for(int i=0;i<size;i++)
     PrintObject(objects[i]);
 }
//+------------------------------------------------------------------+
//| オブジェクトポインタの配列を渡す                                           |
//+------------------------------------------------------------------+
void PrintPointersArray(Foo* &objects[])
 {
  int size=ArraySize(objects);
  for(int i=0;i<size;i++)
     PrintObject(objects[i]);
 }
//+------------------------------------------------------------------+

 

使用前にポインタを確認

不正なポインタを呼び出す試みはプログラムの緊急終了を生じます。CheckPointer関数を使用して、使用前にポインタをチェックします。ポインタは、次のような場合に不正であることがあります。

  • ポインタがNULLに等しい
  • delete演算子を使用してオブジェクトが破棄されました。

この関数は、ポインタの検証に使用できます。ゼロ以外の値は、このポインタでデータにアクセスできることを示します。

class CMyObject
{
protected:
double             m_value;
public:
                    CMyObject(void);
                    CMyObject(double value) {m_value=value;};
                   ~CMyObject(void){};
//---
double             Value(void) {return(m_value);}
};
//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数                                              |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 初期化されていないオブジェクトを作成する
CMyObject *pointer;
if(CheckPointer(pointer)==POINTER_INVALID)
  Print("1. pointer is ", EnumToString(CheckPointer(pointer)));
else
  Print("1. pointer.Value()=", pointer.Value());
 
//--- ポインタを初期化する
pointer=new CMyObject(M_PI);
if(CheckPointer(pointer)==POINTER_INVALID)
  Print("2. pointer is ", EnumToString(CheckPointer(pointer)));
else
  Print("2. pointer.Value()=", pointer.Value());
 
//--- オブジェクトを削除する
delete(pointer);
if(CheckPointer(pointer)==POINTER_INVALID)
  Print("3. pointer is ", EnumToString(CheckPointer(pointer)));
else
  Print("3. pointer.Value()=", pointer.Value());
}
/*
  1. pointer is POINTER_INVALID
  2. pointer.Value()=3.141592653589793
  3. pointer is POINTER_INVALID
*/

ポインタをすばやく検証するにはCheckPointer関数の暗黙的な呼び出しを介してチェックする演算子「!」(LNOT)も使用できます。これにより、より簡潔で明確なコードを記述できます。以下は前の例のチェックです。

//+------------------------------------------------------------------+
//| スクリプトプログラム開始関数                                              |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 初期化されていないオブジェクトを作成する
CMyObject *pointer;
if(!pointer)
  Print("1. pointer is ", EnumToString(CheckPointer(pointer)));
else
  Print("1. pointer.Value()=", pointer.Value());
 
//--- ポインタを初期化する
pointer=new CMyObject(M_PI);
if(!pointer)
  Print("2. pointer is ", EnumToString(CheckPointer(pointer)));
else
  Print("2. pointer.Value()=", pointer.Value());
 
//--- オブジェクトを削除する
delete(pointer);
if(!pointer)
  Print("3. pointer is ", EnumToString(CheckPointer(pointer)));
else
  Print("3. pointer.Value()=", pointer.Value());
}
/*
  1. pointer is POINTER_INVALID
  2. pointer.Value()=3.141592653589793
  3. pointer is POINTER_INVALID
*/

演算子「==」は、NULL のクイック チェックに使用されます。例:ptr==NULLまたはptr!=NULL。

参照

変数変数の初期化変数のアクセス権スコープとライフタイムオブジェクトの作成と解徐