Примеры реализации
В предыдущем параграфе рассматривался пример
исполнения специальных функций в простом эксперте
simple.mq4. Для того, чтобы закрепить
материал, необходимо рассмотреть ещё несколько модификаций этой программы.
|
Пример правильной структуры программы |
Как правило, описания
функций в программе указываются в той последовательности, в которой они
вызываются для исполнения клиентским терминалом, а именно, сначала приводится описание
специальной функции init(), затем специальной функции
start(), и последним указывается описание специальной функции
deinit(). Однако специальные функции вызываются для
исполнения клиентским терминалом в соответствии с их собственными свойствами,
поэтому не имеет значения, в каком месте программы указано описание той или иной
функции. Давайте переставим местами специальные функции и посмотрим, что из этого получится
(эксперт
possible.mq4).
int Count=0;
int start()
{
double Price = Bid;
Count++;
Alert("Новый тик ",Count," Цена = ",Price);
return;
}
int init()
{
Alert ("Сработала ф-ия init() при запуске");
return;
}
int deinit()
{
Alert ("Сработала ф-ия deinit() при выгрузке");
return;
}
Запустив этот эксперт на выполнение, легко убедиться, что порядок исполнения специальных функций в программе не зависит от порядка
следования в программе описаний специальных функций. Вы можете самостоятельно по своему
выбору поменять местами специальные функции в исходном коде и убедиться, что для любого
варианта результат будет таким же, как и в
случае исполнения эксперта simple.mq4.
|
Пример неправильной структуры программы |
Совсем иные события произойдут, если в программе изменить положение головной
части. В данном примере специальная функция start()
указана раньше (выше по тексту), чем головная часть программы (эксперт incorrect.mq4):
int start()
{
double Price = Bid;
Count++;
Alert ("Новый тик ",Count," Цена = ",Price);
return;
}
int Count=0;
int init()
{
Alert ("Сработала ф-ия init() при запуске");
return;
}
int deinit()
{
Alert ("Сработала ф-ия deinit() при выгрузке");
return;
}
При попытке компиляции этого эксперта редактор MetaEditor выдаст сообщение об ошибке:
Рис. 36. Сообщение об ошибках при компиляции программы
incorrect.mq4.
В данном случае строка
int Count=0;
написана за пределами всех функций, но находится не в первых строках программы,
а где-то в середине.
Определяющим моментом в структуре этой программы является то, что объявление глобальной
переменной Count происходит после объявления функции (в данном случае - специальной
функции start()). На данном этапе изложения мы не можем обсуждать подробности применения
глобальных переменных; виды переменных и правила их использования приведены в разделе
Переменные. Здесь достаточно сказать, что любая глобальная переменная должна быть объявлена
раньше (выше по тексту программы), чем первое обращение к этой переменной (в
данном случае из функции start()). В рассматриваемой
программе это правило нарушено, поэтому компилятор сообщил об ошибке.
|
Пример применения пользовательской функции |
Теперь посмотрим, как программа проявляется в отношении пользовательских функций.
Для этого несколько модернизируем код, представленный в примере
простого эксперта simple.mq4, и подробно
его разберём. Программа, содержащая пользовательскую
функцию, будет выглядеть так (эксперт userfunction.mq4):
int Count=0;
int init()
{
Alert ("Сработала ф-ия init() при запуске");
return;
}
int start()
{
double Price = Bid;
My_Function();
Alert("Новый тик ",Count," Цена = ",Price);
return;
}
int deinit()
{
Alert ("Сработала ф-ия deinit() при выгрузке");
return;
}
int My_Function()
{
Count++;
}
Прежде всего, посмотрим, какие внесены изменения и какая часть кода осталась нетронутой.
Остались без изменений:
1. Головная часть осталась без изменений.
int Count=0;
2. Специальная функция init() осталась без изменений.
int init()
{
Alert ("Сработала ф-ия init() при запуске");
return;
}
3. Специальная функция deinit() осталась без изменений.
int deinit()
{
Alert("Сработала ф-ия deinit() при выгрузке");
return;
}
Изменения:
1. Добавилась пользовательская функция My_Function().
int My_Function()
{
Count++;
}
2. Претерпел изменение код специальной функции start(): в нём появилось обращение
к пользовательской функции, а также отсутствует строка вычисления переменной Count.
int start()
{
double Price = Bid;
My_Function();
Alert("Новый тик ",Count," Цена = ",Price);
return;
}
В разделе Выполнение программы рассматривался порядок исполнения специальных функций init() и deinit(). В данном
примере исполнение этих функций будет происходить так же, поэтому здесь нет необходимости
останавливаться на их работе. Рассмотрим исполнение специальной функции start()
и пользовательской функции My_Function(). Описание пользовательской функции расположено за пределами всех специальных функций,
как и должно быть. Вызов пользовательской функции указан в коде специальной функции start(),
что тоже верно.
После того, как исполнится специальная функция init(),
программа будет исполняться так:
31. Специальная функция start() находится в ожидании запуска клиентским терминалом.
С приходом нового тика терминал запустит функцию start() на исполнение, в результате
чего произойдут следующие события:
32 (1). В строке
double Price = Bid;
производятся те же действия:
32.1(1). Инициализация локальной переменной Price (см.
Виды переменных). Значение этой локальной переменной будет доступно из любого места специальной
функции start().
32.2(1). Выполнение оператора присваивания. Переменной Price будет присвоено последнее
известное значение текущей цены Bid (например, на первом тике цена финансового
инструмента окажется равной 1.2744).
33(1). Следующей записью в коде является обращение к пользовательской функции My_Function():
My_Function();
Эта строка будет исполнена в рамках продолжающейся работы специальной функции start().
Результатом выполнения этой части кода (обращение к пользовательской функции) будет
передача управления в тело (описание) пользовательской функции с последующим возвратом
управления в место вызова.
34(1). В описании пользовательской функции имеется всего один оператор:
Count++;
При первом вызове пользовательской функции значение переменной Count равно нулю.
В результате выполнения оператора Count++ значение переменной Count будет увеличено
на единицу. Исполнив этот оператор (единственный и последний) пользовательская
функция заканчивает свою работу и передаёт управление в то место, откуда она была
вызвана.
Необходимо подчеркнуть, что пользовательские функции могут быть вызваны для работы
только из специальных функций ( или из других пользовательских, которые в конечном
счёте всё равно вызваны из специальных). Поэтому справедливым является утверждение,
что в любой текущий момент работает одна из специальных функций (или специальная
функция start() может находиться в состоянии ожидания нового тика - запуска её на
исполнение клиентским терминалом), а пользовательские функции исполняются лишь
в рамках исполнения специальных функций.
В данном случае управление возвращается в (исполняющуюся) специальную функцию start(),
а именно в строку, следующую за оператором вызова функции:
35(1). В этой строке содержится вызов функции Alert():
Alert ("Новый тик ",Count," Цена = ",Price);
Функция Alert() выведет в окно сообщения все константы и переменные, перечисленные
в круглых скобках:
Новый тик 1 Цена = 1.2744 |
36(1). Оператор
return;
заканчивает работу специальной функции start().
37. Управление передаётся клиентскому терминалу на ожидание нового тика.
При следующих исполнениях специальной функции start() переменные получат новые значения
и снова будут выведены в окно сообщения функции Alert(), т.е. программа снова выполнится
по пп 32 - 36. В том числе, при каждом исполнении функции start() (на каждом тике)
будет срабатывать обращение к пользовательской функции My_Function(), и эта функция
будет выполняться. Исполнение специальной функции start() будет продолжаться до
тех пор, пока пользователь не примет решение о прекращении работы программы. В
этом случае отработает специальная функция deinit() и программа прекратит свою
работу.
Запущенная на исполнение программа userfunction.ех4 отобразит на экране окно,
в котором будут выводиться сообщения функции Alert(). Обратите внимание, результат
работы программы будет таким же, как и результат работы простого
эксперта simple.mq4. Легко увидеть, что структура программы userfunction.mq4
составлена в соответствии с обычным порядком
расположения функциональных блоков.
Если же этот порядок изменить на другой допустимый порядок, то результат работы программы не изменится.