文章 "在 MQL5 中使用对象指针"

 

新文章 在 MQL5 中使用对象指针已发布:

默认情况下,MQL5 中的所有对象都通过引用传递,但还有使用对象指针的可能性。然而,由于对象可能没有初始化,我们必须执行指针检查。在这种情况下,MQL5程序可能会因为关键性错误而终止并卸载。自动创建的对象不会引起此类错误,因此就此意义而言它们十分安全。通过本文,我们将理解对象引用和对象指针之间的差异,并思考如何编写使用指针的安全代码。

在 MQL5 中,您可能会创建自己的类以在代码中进一步使用该类类型的变量。我们已从前文 MQL5 中对象创建和析构的顺序中学到,结构和类可以通过两种方式创建 - 自动和动态。

要自动创建对象,只需声明一个类类型变量 - 系统将自动创建对象并初始化对象。要动态创建对象,必须显式地将运算符 new 应用至对象指针。

然而,自动创建的对象和动态创建的对象之间有何区别,哪些情况下必须使用对象指针而哪些情况下自动创建对象即已足够?本文正是旨在回答上述问题。首先,我们探讨使用对象时易犯的错误,以及相应的解决方法。

访问无效指针时产生的关键性错误

首先,您应当记住,在使用对象指针时必须先初始化对象然后才能使用对象。在您访问无效指针时,MQL 程序会因关键性错误而停止执行,因此程序被移除。我们将一个简单的“EA 交易”作为示例,该“EA 交易”具有类 CHello 并在此声明。类实例的指针声明为全局级别

作者:MetaQuotes Software Corp.

 

文本中的源代码应与所附文件保持一致,特别是在 GetCriticalError_Unsafe.mq5 清单中,引用的是不存在的变量 status,而不是 pstatus(与文件中一致)。

在每个 CShape 继承类中定义自己的变量类型有什么意义?

我还想听听对此的解释。当从 GetCriticalError_OnDemand 示例切换到 GetCriticalError_Unsafe 时,整个变化实际上就是将函数参数的类型从 CHello *pobject 变为 CHello &pobject。与此同时,函数调用保持不变 - 传递了一个指针(CHello *)。在这种情况下,根据作者的说法,"我们再次出现严重错误。关键在于,如果对象是通过引用传递的,那么在调用函数时,未初始化的对象 被传递到函数中,这时就会出现临界错误"。 但在这种情况下,传递给函数的是指针而不是引用。问题是它从何而来。能否请您详细说明 MQL5 用于将指针隐式转换为引用并返回的规则?或者指出文档中对此进行描述的地方。如果编译器支持严格类型,那么该示例就会因为缺少具有所需类型参数的函数而无法编译。

 
marketeer писал(а) # :

文中的源代码应与所附文件保持一致,特别是在 GetCriticalError_Unsafe.mq5 清单中,引用了一个不存在的变量 status,而不是 pstatus(与文件中一致)。

谢谢,已在文章和文件中更正。

 
marketeer писал(а) # :

在每个 CShape 继承类中定义自己的类型变量有什么意义?

原则上,该成员在任何地方都不会被使用,您可以将其删除。从理论上讲,它可以在后代中用于实现依赖于对象类型的函数。
 
marketeer писал(а) # :
我也想听听对这个问题的一些澄清。当从 GetCriticalError_OnDemand 示例切换到 GetCriticalError_Unsafe 时,整个变化实际上就是将函数参数的类型从 CHello *pobject 变为 CHello &pobject。与此同时,函数调用保持不变 - 传递了一个指针(CHello *)。在这种情况下,根据作者的说法,"我们再次出现严重错误。问题是,如果对象是通过引用传递的,那么在调用函数的阶段,未初始化的对象 被传递到函数中时,就会出现严重错误"。 但在这种情况下,传递给函数的是指针而不是引用。问题是它从何而来。能否请您详细说明 MQL5 用于将指针隐式转换为引用并返回的规则?或者指出文档中对此进行描述的地方。如果编译器支持严格类型,那么该示例将无法编译,因为不存在具有所需类型参数的函数。
如果明确定义 了接受参数为指针的函数,就会使用该函数。如果没有这样的函数,对象指针将自动转换为对象引用,并使用接受对象引用的函数。
 
Rosh писал(а) # :
原则上,该成员不会在任何地方使用,可以将其删除。理论上,它可以在后代中用于实现依赖于对象类型的函数。
我的理解是,根据当前示例的源代码,我们会得到一个 "耙子",即在特定类型的形状对象中有两个类型变量,例如,除了 CShape::type 之外,还有 CLine::type?理想情况下,应该只有一个--来自基类。
 
Rosh писал(а) # :
如果明确定义 了接受参数为指针的函数,则将使用该函数。如果没有这样的函数,对象的指针将自动转换为对象的引用,并使用接受对象引用的函数。
是否有地方可以了解有关引用和指针的隐式转换的方向?特别是,是否也进行反向转换--从引用到指针?
 
marketeer писал(а) # :
有没有地方可以让我了解对引用和指针进行隐式转换的方向?特别是,是否也进行反向转换--从引用到指针?
不,要获取对象指针,请使用GetPointer()
Документация по MQL5: Общие функции / GetPointer
Документация по MQL5: Общие функции / GetPointer
  • www.mql5.com
Общие функции / GetPointer - Документация по MQL5
 
marketeer писал(а) # :
我的理解是否正确,根据当前示例的源代码,我们得到的 "耙 "是,在一个特定类型的形状对象中,有两个类型变量,例如,除了 CShape::type 之外,还有 CLine::type?理想情况下应该只有一个--来自基类。

是的,你说得对。正如你所写的,每个子类都有两个类型变量。出现这种情况是因为复制了子类的代码。要使基类中的某个成员直接对子类可用,应在基类中使用protected 指定符 定义该成员,或声明该成员的公共 get 和 set 方法。

例如

//+------------------------------------------------------------------+
//|demo_inheritance.mq5
//| 2010 年,MetaQuotes 软件公司版权所有。
//|http://www.mql5.com | |
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CBase
  {
private:
   int               type;
public:
                     CBase(){type=0;}
   int               GetType(){return(type);}
  };
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CSon: CBase
  {
private:
   int               type;
public:
                     CSon(){type=2;}
   void              PrintType();
  };
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void CSon::PrintType()
  {
   Print("CSon.type =",type);
   Print("CBase.type =",CBase::GetType());
  }
//+------------------------------------------------------------------+
//| 脚本程序启动功能|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   CSon  son;
   son.PrintType();
   int father_type=son.GetType();
  }
//+------------------------------------------------------------------+
 
引用:

"这个示例非常简单,不难发现其中的错误。但如果您的 mql5 程序包含数百行甚至数千行,查找此类错误就会变得复杂得多。尤其是当程序行为的异常情况取决于不可预测的因素(例如,某个市场)时"。

怎么做?)

 
这是指夫妻双方的具体情况在某些方面有所不同。