目标指针

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());
 }
/*
   1pointer is POINTER_INVALID
   2pointer.Value()=3.141592653589793
   3pointer 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());
 }
/*
   1pointer is POINTER_INVALID
   2pointer.Value()=3.141592653589793
   3pointer is POINTER_INVALID
*/

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

另见

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