函数声明
函数声明说明了一个原型,但没有指定函数体。放置了一个分号,而不是一个有主体的代码块。
声明对于编译器来说是必要的,这样编译器才能在后续代码片段中检查函数调用是否正确(包括按名称调用、向它传递自变量和获得结果)。
整个函数定义(包括函数体)也是一个声明,所以除了定义之外不需要声明函数。
例如,上述 Fibo 函数的声明是这样的。
int Fibo(const int n); |
从几个带有源文本的文件构建程序时,将使用单独的函数声明和定义:然后在扩展名为 mqh 的头文件中进行声明(参见 #include 预处理程序指令一节),这个头文件包含在使用该函数的文件中,函数定义仅在其中一个文件中实现。函数签名在声明和定义中的匹配提供了防错功能。也就是说,单个声明保证了对整个源代码所做更改的一致性。
如果我们声明一个函数并在代码的某处调用该函数,但没有为其提供完全合适的定义,编译器将抛出一个错误:“函数‘名称’必须有一个主体”。这种情况经常发生,比如因为声明或定义中有拼写错误或不准确,以及在更改源代码的过程中,一些更正已经完成,而另一些很可能被遗忘。
如果函数被声明但没有在任何地方使用,编译器也不需要这个函数的定义 - 这个元素就从二进制程序中“切掉”了。
在 声明/定义语句 一节中,我们分析了 Init 函数的一个例子(StmtDeclaration.mq5 脚本),该函数用于初始化变量。其中特别说明了一个问题,全局变量 k 不能在 Init 函数之前定义,因为初始值 k 是通过调用 Init 获得的。编译器会抛出错误“'Init' 是未知标识符”。
现在我们知道,这样的问题可以通过一个声明来解决。在 FuncDeclaration.mq5 脚本中,我们在 k 变量之前添加了以下 Init 函数的前向声明,并将 Init 定义留在 k 之后。
// preliminary declaration
|
现在脚本可以正常编译了。从技术上讲,在这种情况下,我们只需将函数移到变量上方,而不需要预先声明。这样做是为了解释这个概念。然而,在某些语言元素相互依赖的情况(如类)下,即使是在同一文件中也必须使用前置声明。