从基础到中级:Include 指令·综合运用
📘

从基础到中级:Include 指令·综合运用

第 3/3 篇

◍ 把改过的头文件放进 include 中心目录

MT5 客户端每次推送更新,都会重写 MQL5 目录下的 include 文件夹。如果你把自改或他人分发的头文件直接丢进默认 include,下一次自动升级就可能无声覆盖掉它,辛苦攒的实用修改瞬间清零。 更稳的做法是把这类文件集中存到 include 目录里做统一版本管理,同时务必定期备份。个人经验上,用 GIT 做版本控制能避开大量文件丢失和回滚的麻烦,只是得先花时间学清楚基本操作。 现在我们可以在 include 中维护同一头文件的两个副本:一个仅限当前项目引用,另一个供你写的所有脚本共用。下面这段就是把上一节的 File 01 思路挪进 include 后,被多个程序共享的 File 04 内容,里面 One_Radians 函数返回 180/M_PI,即约 57.2958。 [CODE]

  • //+------------------------------------------------------------------+
  • #property copyright "Daniel Jose"
  • //+------------------------------------------------------------------+
  • double One_Radian()
  • {
  • return 180. / M_PI;
  • }
  • //+------------------------------------------------------------------+
  • double ToRadians(double angle)
  • {
  • return angle / One_Radian();
  • }
  • //+------------------------------------------------------------------+
  • double ToDegrees(double angle)
  • {
  • return angle * One_Radian();
  • }
  • //+------------------------------------------------------------------+
  • //+------------------------------------------------------------------+
  • #property copyright "Daniel Jose"
  • //+------------------------------------------------------------------+
  • #include "Tutorial\File 01.mqh"
  • #include "Tutorial\File 02.mqh"
  • #include "Tutorial\File 03.mqh"
  • //+------------------------------------------------------------------+
  • void OnStart(void)
  • {
  • ulong value;

11.

  • Print("Factorial of 5: ", Factorial(5));
  • Print("Factorial of 3: ", Factorial(3));
  • Print(One_Radian());
  • Print(ToRadians(90));
  • do
  • {
  • value = Tic_Tac();
  • Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", value);
  • }while (value < 3);

[/CODE] 上面代码 04 直接编译会报错,根因在第 15 行调用的 ToRadians 依赖 One_Radian,但所包含的三个头文件里并没有提供它,编译器必然失败。修正方式只是把 include 路径指向 include 中心目录中正确的 File 04,而非项目局部的 File 01,改动极小却直接决定编译能否通过。 别把同名函数当无害重叠 多个头文件里塞同名函数,MT5 编译器不会替你智能选优,冲突全看你怎么排 include 顺序和路径。真到项目变大时,这种坑只能靠自己理清依赖,没有通用一键解法。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| File class="num">04 (shared in include)                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">double One_Radian()
{
   class="kw">return class="num">180. / M_PI;
}
class="type">class="kw">double ToRadians(class="type">class="kw">double angle)
{
   class="kw">return angle / One_Radian();
}
class="type">class="kw">double ToDegrees(class="type">class="kw">double angle)
{
   class="kw">return angle * One_Radian();
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Caller using include-centered headers                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include "Tutorial\File class="num">01.mqh"
class="macro">#include "Tutorial\File class="num">02.mqh"
class="macro">#include "Tutorial\File class="num">03.mqh"
class="type">void OnStart(class="type">void)
{
   class="type">ulong value;
   Print("Factorial of class="num">5: ", Factorial(class="num">5));
   Print("Factorial of class="num">3: ", Factorial(class="num">3));
   Print(One_Radian());
   Print(ToRadians(class="num">90));
   do
   {
      value = Tic_Tac();
      Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", value);
   }while (value < class="num">3);

把三个头文件拼进主脚本跑一遍

这段主程序把前几节拆出去的 File 01~03 三个 mqh 全部 include 进来,在 OnStart 里依次验证各函数是否按预期返回。Factorial(5) 应输出 120,Factorial(3) 为 6,One_Radian 返回 1 弧度对应的浮点值,ToRadians(90) 则返回约 1.5708,这些数字可以直接在 MT5 策略测试器的日志里核对。 Tic_Tac 是个带内部计数的函数,do-while 循环会一直调用直到返回值大于等于 3 才退出,说明它内部状态在跨调用间被保留。第 21 行传 true 参数疑似强制重置计数,第 22 行无参继续累加,日志里能看到 __FUNCTION__ 和 __LINE__ 帮你在多文件工程里快速定位输出来源。 include 写法有两种:尖括号 <Tutorial\File 01.mqh> 走标准搜索路径,双引号 "Tutorial\File 02.mqh" 优先查当前工程目录。自己写指标时若提示找不到文件,先确认是路径权限问题还是引号类型用错。外汇与贵金属行情受杠杆与跳空影响,回测日志仅验证代码逻辑,不代表任何实盘收益可能。

MQL5 / C++
class="num">01. class=class="str">"cmt">//+------------------------------------------------------------------+
class="num">02. class="macro">#class="kw">property copyright "Daniel Jose"
class="num">03. class=class="str">"cmt">//+------------------------------------------------------------------+
class="num">04. class="macro">#include <Tutorial\File class="num">01.mqh>
class="num">05. class="macro">#include "Tutorial\File class="num">02.mqh"
class="num">06. class="macro">#include "Tutorial\File class="num">03.mqh"
class="num">07. class=class="str">"cmt">//+------------------------------------------------------------------+
class="num">08. class="type">void OnStart(class="type">void)
class="num">09. {
class="num">10.    class="type">ulong value;
class="num">11.
class="num">12.    Print("Factorial of class="num">5: ", Factorial(class="num">5));
class="num">13.    Print("Factorial of class="num">3: ", Factorial(class="num">3));
class="num">14.    Print(One_Radian());
class="num">15.    Print(ToRadians(class="num">90));
class="num">16.    do
class="num">17.    {
class="num">18.       value = Tic_Tac();
class="num">19.       Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", value);
class="num">20.    }while (value < class="num">3);
class="num">21.    Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac(true));
class="num">22.    Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac());
class="num">23. }
class="num">24. class=class="str">"cmt">//+------------------------------------------------------------------+

「把常用片段收进自己的头文件」

这一篇只拆了一个编译指令的侧面,但真要把它用顺手,靠的不是背语法,而是把自己的开发身份理顺。把反复要写的判断、宏、工具函数塞进专属头文件并分门别类,下次开 MT5 写 EA 或指标时直接 include,省下的调试时间会肉眼可见。 评论区里作者自己认了一处笔误:本想讲 #if 指令,落笔写成了 #ifdef,而后者在 MQL4/MQL5 里早就长期存在、等同于 C/C++ 的 #if defined。这种错不致命,却提醒你抄代码前先核对指令语义,别把预处理宏当黑盒。 迈出第一步就是现在:在 MT5 的 MQL5/Include 下建一个 my_utils.mqh,把今天看到的代码块存进去,下次新建文件顶部写一行 #include <my_utils.mqh>。外汇与贵金属杠杆交易高风险,代码只管工程效率,不管仓位生死。

常见问题

放到交易软件的安装目录下的 Include 中心目录即可,主脚本用 #include 就能直接找到,不用写完整路径。
先确认三个头文件里没有重名函数,且主脚本的 include 顺序和依赖关系正确,再重新编译一次。
可以,小布能读取你的头文件结构并提示重名、缺失依赖等常见问题,省去手动逐个翻看的麻烦。
把那段逻辑单独存成一个 .mqh 风格的头文件放进 Include 目录,主脚本里用 include 调用就行。
可能让依赖旧接口的其他脚本编译失败,建议备份原文件或新建带版本号的头文件再引用。