Объявление функции

Объявление функции описывает прототип без указания тела функции. Вместо блока с телом ставится точка с запятой.

Объявление необходимо для компилятора, чтобы можно было проверять в последующих фрагментах кода, насколько правильно производится вызов функцию по имени, передача в неё аргументов и получение результата.

Полное определение функции (вместе с телом) также является объявлением, поэтому объявлять функцию в дополнение к определению не требуется.

Например, объявление вышеприведенной функции Fibo могло бы выглядеть следующим образом.

int Fibo(const int n);

Раздельное объявление и определение функций используется при сборке программы из нескольких файлов с исходным текстом: тогда объявление делается в заголовочном файле с расширением mqh (см. раздел про директиву препроцессора #include), который включается в файлы, где функция используется, а определение функции реализуется лишь в одном из файлов. Совпадение сигнатуры функции в объявлении и определении обеспечивает защиту от ошибок. Иными словами, единственное объявление гарантирует согласованность вносимых во весь исходный код правок.

Если мы объявим функцию и вызовем её где-то в коде, но не предоставим для неё полностью соответствующее определение, компилятор выдаст ошибку: "функция 'Имя' должна иметь тело" ("function 'Name' must have a body"). Это часто бывает при опечатках или неточностях либо в объявлении, либо в определении, а также в процессе изменения исходных кодов, когда часть исправлений уже внесена, а про другую часть, скорее всего, забыли.

Если функция объявлена и нигде не используется, компилятор не требует и её определения — такой элемент просто "вырезается" из бинарной программы.

В разделе Инструкции объявления/определения мы рассматривали пример функции Init (скрипт StmtDeclaration.mq5), которая использовалась для инициализации переменных. Там, в частности, была продемонстрирована проблема, связанная с тем, что глобальная переменная k не может быть определена до функции Init, поскольку начальное значение k получается в результате вызова Init. Компилятор выдавал ошибку "'Init' - неизвестный идентификатор".

Теперь мы знаем, что такую проблему можно решить с помощью объявления. В скрипте FuncDeclaration.mq5 мы добавили такое предварительное объявление (forward declaration) функции Init перед переменной k, а определение Init оставили после k.

// предварительное объявление
int Init(const int v);
// до добавления предварительного объявления выше
// тут возникала ошибка: 'Init' - неизвестный идентификатор
int k = Init(-1);
int Init(const int v)
{
   Print("Init: "v);
   return v;
}

Теперь скрипт компилируется нормально. В принципе, в данном случае можно было без предварительного объявления просто перенести функцию выше переменной. Мы сделали это для объяснения концепции. Однако бывают случаи взаимной зависимости элементов языка друг от друга (например, классов), когда без предварительного объявления в пределах одного файла не обойтись.