MQL5 对象指针:为什么需要、如何安全使用
指针、CheckPointer、函数重载,以及链表与多态为何离不开指针
MQL5 是面向对象的语言,但大多数时候你写的对象(指标句柄封装、CTrade 等)都由系统自动管理。只有在链表、多态这类需要“把对象连起来”或“同一接口跑不同行为”的场景,才需要用到对象指针。指针很强大,也很容易把 EA 直接搞崩——本文先把坑讲清楚,再给安全写法。
一、对象的两种创建方式
声明一个类类型的变量(如 CHello h),系统会“自动创建”并初始化对象,生命周期跟随变量作用域。使用 new 运算符(如 CHello *p = new CHello)则是“动态创建”,返回的是一个指向该对象的指针,需要你手动 delete 释放。
二、对象指针是什么(以及不是什么)
指针是指向类实例的变量(如 CHello *pstatus)。在 MQL5 里它并非 C++ 意义上的真实内存地址,不能当作 DLL 的输入参数使用。如果在全局作用域声明了指针,却忘了用 new 初始化就直接调用它的方法,程序会在 OnInit 阶段触发“关键性错误”并卸载 EA。
三、用 CheckPointer() 守住安全底线
函数 CheckPointer(p) 在指针无效时返回 POINTER_INVALID。正确写法是:任何接收指针的函数,先检查再调用——无效就提示“对象未被初始化”,而不是直接崩溃。
- 把指针作为函数参数时,函数体内第一件事就是 CheckPointer(p)
- 无效指针只打印告警,绝不触碰它的方法
- 析构要 paired:new 出来的一律在析构函数里 delete
四、函数重载:一套接口兼容指针与引用
如果你既想支持传指针、又想支持传引用,可以写两个同名函数:一个接收指针(安全版),一个接收引用(内部用 GetPointer(object) 转成指针,再调用安全版)。这样无论调用方怎么传,都不会触发关键性错误。
五、什么时候必须用指针
链表靠 m_next / m_prev 指针把前后项串起来(标准库 CList 就是如此),析构时递归 delete 回收;多态则靠“基类指针数组”指向不同派生类对象,配合 virtual 函数在运行期绑定真实类型——基类指针调用 virtual getTypeName() 时,输出的是派生类的真实名字而非“Shape”。
小结
- 对象有自动创建与 new 动态创建两种,后者返回指针
- MQL5 指针不是真实内存地址,不能传给 DLL
- 未初始化指针在 OnInit 调用会触发关键性错误
- CheckPointer() 是安全底线,函数内先检查再调用
- 函数重载可同时兼容指针与引用,避免崩溃
- 链表与多态是必须用指针的两类典型场景