从基础到中级:Include 指令·综合运用
◍ 把改过的头文件放进 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 顺序和路径。真到项目变大时,这种坑只能靠自己理清依赖,没有通用一键解法。
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" 优先查当前工程目录。自己写指标时若提示找不到文件,先确认是路径权限问题还是引号类型用错。外汇与贵金属行情受杠杆与跳空影响,回测日志仅验证代码逻辑,不代表任何实盘收益可能。
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>。外汇与贵金属杠杆交易高风险,代码只管工程效率,不管仓位生死。