目标指针

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); // 对象指针由编译器自动转换



//--- 声明Foo对象的数组

   Foo foo_objects[5];

//--- 传递对象数组的变体

   PrintObjectsArray(foo_objects); // 用于传递对象数组的单独函数



//--- 声明指向Foo类型对象的指针数组

   Foo *foo_pointers[5];

   for(int i=0;i<5;i++)

      foo_pointers[i]=new Foo("foo_pointer");

//--- 传递指针数组的变体

   PrintPointersArray(foo_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

*/

要快速验证指针,您还可以使用操作符"!" (LNOT)通过隐式调用CheckPointer函数来检查。这允许更简洁和清晰的代码编写。以下是上一个示例中的检查:

//+------------------------------------------------------------------+

//| 脚本程序起始函数                                                   |

//+------------------------------------------------------------------+

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

*/

Operator "==" is used for a quick check for NULL. 例如:ptr==NULL或ptr!=NULL。

另见

变量初始变量变量可见范围和使用期限创建和删除目标