MQL5语言帮助文件人话版(三十二)第四章(4) 函数的使用

| 发表于 昨天 13:37 | 显示全部楼层 |复制链接
三、重载函数
这里的重是重复是意思,不是重量的重,也不是重新的重。重载函数就是,同一个函数名,多个参数版本,本质上就是同功能不同参数的一系列“重复(仅指函数名称)”函数。

我们之前说过,编程写名字,要望文知意,这是高级语言的灵魂。而函数一定是对应某种功能的处理过程,它的名字一定能够让你知道这是做什么用的函数。比如打印函数Print();,print这个单词就是打印的意思。我自己写一个K线形态函数,判断两个K线是否是包含关系的函数:bool CheckContainedStatus(double high0, double low0,  double high1, double low1);,Check意思是检查,Contained意思是包含,Status意思是状态,反正又没限制命名的长度,我就把这三个单词罗列在一起,任谁看了这个名字,都知道它做是否包含关系判断的。当然我也可以写成bool CCS()甚至用无任何意义的字母组合bool ABC()来写这个函数,完全不会影响这函数的定义和使用,但下回再看到它,怕是自己都不认得了。

但是,有时候会出现功能相同,内容不同的情况。最明显的就是这个Print();。新手可能听到它是个函数的时候,会很费解,它难道是个没有参数的函数吗?正好相反,它是一个拥有不限制参数的函数,不限制参数个数,不限制参数类型,不限制参数顺序(这叫可变参数技术,不用深究,我们用不着)。你无论打印整数、浮点数、文本字符串还是其他什么东西, 是打印一个还是多个内容,其本质都是“打印输出”,这个功能不会因为打印函数参数不同而不同。所以同样功能,不同参数的函数,没必要各写一个函数名,没必要弄一个单参数打印函数,多参数打印函数,整数打印函数,字符串打印函数。

所以,重载函数的本质就是:「同名不同参」的多版本函数,同一个功能用同一个函数名,针对不同的输入参数(数量、类型、顺序)定义多个实现版本;编译器会根据你调用时传的实参,自动匹配对应的版本。

重载只看参数的数量、类型、顺序,只要这三个有一个不一样,就算不同的重载版本;重载不看具体的参数名称,多个同类型但不同名的参数,调整顺序,或者只更换参数名称,系统依旧当同一个函数,进行重复定义报错;参数完全一致,但返回值类型不同,也不算重载,系统也会进行重复定义报错。

当调用函数时,系统根据你输入的实参的数量、类型、顺序,自动匹配相应的函数;但当参数出现隐式转换时,比如浮点数转换为整数,系统很可能会出错,尽量避免这种情况。

原手册上的“操作重载”,实际上是“运算符重载”。你可以这样理解,像+、-、*、>、@这些运算操作符,本质上也是一种函数。比如@,就是前面暂时忽略的矩阵乘法运算符,它原本长这样:MatrixMultiply(A, B),A和B代表两个矩阵,但系统通过“运算符重载”,把这个符号等同于了这个函数,你就可以直接写A@B了。这个技术的目的是让运算函数更像我们日常理解的那样去表达,我们实际写EA的时候基本上用不到这个概念,了解一下即可。

四、跨模块(单独的代码文件)调用外部函数的语法规则
原手册中叫“外部函数描述”,理解起来确实费脑子。

如果某个函数不是在当前这个代码文件里写的,而是定义在别的「模块」(独立的代码文件)里,那你在当前文件调用它之前,必须先写出它的函数声明(原型)。所谓「模块」就是独立的代码文件。代码量大了之后,不会把所有逻辑都塞在一个 EA 文件里,通常会拆分成:工具函数模块、指标计算模块、交易风控模块等,每个文件就是一个模块。

这个外部函数的声明,格式要求和我们之前学的「同文件前向声明」完全一样:必须写全返回值类型、函数名、参数列表(每个参数的类型),不能缺项。不写这个声明的话,编译器把多个模块拼接成完整程序的时候,就会找不到这个函数的定义,会直接报 “未定义函数” 错误,程序跑不起来。光写函数声明还不够,还要用 `#import` 这个预处理指令,明确告诉编译器:这个外部函数到底在哪个文件里。

`#import` 不仅能导入源码,还能导入 EX5、DLL 二进制库,用法和之前学的跨文件导入基本一致;这种方式适合复用通用工具、保护核心算法、商业化分发策略组件,属于进阶知识,我们暂且不讨论。

在新手阶段,写一些简单代码,完全没必要划分模块,但我强烈建议把模块化设计当作基本功来训练,设计模块本身就是在设计架构,将来你总归要开发复杂EA的,没有架构设计思路,脑子里永远都是一锅粥,是无法驾驭复杂EA的。

正像原手册例子中的那样,#import"user32.dll"、#import"lib.ex5",这种跨模块调用通常是用在.ex5 预编译库和.dll 动态链接库上面,当然.mq5 普通源码也可以用#import来调用。但通常我们写的EA不是那么复杂的情况下,我们用#include命令来整个引用子模块会更方便,也不需要做什么劳什子函数声明。

EX5 程序库是MQL5 专属的预编译库。把常用的工具函数、指标算法写成 `.mq5` 文件,编译后生成 `.ex5` 二进制文件 —— 别人看不到你的源码,但可以调用你暴露出来的函数,适合商业化分发、核心算法保护。在函数定义前加上 `export` 关键字标记的函数,允许被其他 MQL5 程序通过 `#import` 调用;这类函数就叫「导出函数」。当你把源码编译生成 `.ex5` 库文件时,编译器会自动把所有加了 `export` 的函数,登记到 EX5 文件头部的导出函数表里 —— 这相当于库的「公开功能目录」,记录了函数名、参数类型等信息。

我们之前说过,函数是一个EA程序的灵魂,如果你写的东西是独创的,不想让人知道其中的逻辑,或者仅仅是不想让比人白票你的代码,那把你的主要函数都编成EX5 程序库就好,想破解它也是有相当难度的,以至于多数人宁可按照你EA的表现去逆向推测你的代码逻辑,也不会想去破解它。

这个语法规则需要度过新手阶段后,通过编写稍微复杂点的EA来实践,这里先只了解概念即可。



最近访问 头像模式
举报

评论 使用道具

发新帖
EA交易
您需要登录后才可以评论 登录 | 立即注册

麻爪

麻爪 D

如果你想让一个人下地狱,介绍他做交易。
如果你想让一个人在地狱里永不超生,介绍他做EA交易。

Fast跟单EA