Назад
Основы языка
© 2000-2011, MetaQuotes Software Corp.
81
struct str1
{
double d;
};
//---
struct str2
{
long l;
};
//---
struct str3
{
int low_part;
int high_part;
};
//+------------------------------------------------------------------+
void OnStart()
{
str1 s1;
str2 s2;
str3 s3;
//---
s1.d=MathArcsin(2.0); // получим недействительное число -1.#IND
s2=s1;
printf("1. %f %I64X",s1.d,s2.l);
//---
s3=s2;
printf("2. high part of long %.8X low part of long %.8X",
s3.high_part,s3.low_part);
}
Еще один пример показывает, как можно организовать собственную функцию для получения из
типа color представления цвета в RGB (Red,Green,Blue). Для этого создаем две структуры,
имеющие одинаковый размер, но разный внутренний состав. Для удобства, добавим в структуру
функцию, возвращающую цвет в представлении RGB в виде строки.
Основы языка
© 2000-2011, MetaQuotes Software Corp.
82
#property script_show_inputs
input color testColor=clrBlue;// задайте цвет для тестирования
//--- структура для представления цвета в RGB
struct RGB
{
uchar blue; // синяя составляющая цвета
uchar green; // зеленая составляющая цвета
uchar red; // красная составляющая цвета
uchar empty; // этот байт не используется
string toString(); // функция для получения в виде строки
};
//--- функция для вывода цвета в виде строки
string RGB::toString(void)
{
string out="("+(string)red+":"+(string)green+":"+(string)blue+")";
return out;
}
//--- структура для хранения встроенного типа color
struct builtColor
{
color c;
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- переменная для хранения в RGB
RGB colorRGB;
//--- переменная для хранения типа color
builtColor test;
test.c=testColor;
//--- приведение двух структур путем копирования содержимого
colorRGB=test;
Print("color ",test.c," = ",colorRGB.toString());
//---
}
Приведение типов указателей базовых классов к указателям производных
классов
Объекты открытопорожденного класса могут также рассматриваться как объекты
соответствующего ему базового класса. Это ведет к некоторым интересным следствиям.
Например, вопреки тому факту, что объекты различных классов, порожденных одним базовым
классом, могут существенно отличаться друг от друга, мы можем создать их связанный список
(List), поскольку мы рассматриваем их как объекты базового типа. Но обратное неверно: объекты
базового класса не являются автоматически объектами производного класса.
Можно использовать явное приведение типов для преобразования указателей базового класса в
указатели производного класса. Но необходимо быть полностью уверенным в допустимости такого
преобразования, так как в противном случае возникнет критическая ошибка времени выполнения
и mql5-программа будет остановлена.
Смотри также
Типы данных
Основы языка
© 2000-2011, MetaQuotes Software Corp.
83
Тип void и константа NULL
Синтаксически тип void является фундаментальным типом наравне с типами char, uchar, bool,
short, ushort, int, uint, color, long, ulong, datetime, float, double и string. Этот тип используется
либо для указания того, что функция не возвращает значения, либо в качестве параметра
функции обозначает отсутствие параметров.
Предопределенная константная переменная NULL имеет тип void. Она может быть присвоена
переменным любых других фундаментальных типов без преобразования. Также допускается
сравнение переменных фундаментальных типов со значением NULL
Пример:
//--- если строка не инициализирована, то присвоим ей наше предопределенное значение
if(some_string==NULL) some_string="empty";
Также NULL можно сравнивать с указателями на объекты, созданные при помощи оператораnew.
Смотри также
Переменные, Функции
Основы языка
© 2000-2011, MetaQuotes Software Corp.
84
Указатели объектов
В MQL5 существует возможность динамически создавать объекты сложного типа. Это делается
при помощи оператораnew, который возвращает описатель созданного объекта. Описатель имеет
размер 8 байт. Синтаксически описатели объектов в MQL5 похожи на указатели в C++.
Примеры:
MyObject* hobject= new MyObject();
Еще раз повторим, что в отличие от C++, переменная hobject из вышеприведенного примера не
является указателем на память, а является дескриптором объекта.
Смотри также
Переменные, Инициализация переменных, Область видимости и время жизни переменных,
Создание и уничтожение объектов
Основы языка
© 2000-2011, MetaQuotes Software Corp.
85
Ссылки. Модификатор & и ключевое слово this
Передача параметров по ссылке
В MQL5 параметры простых типов можно передавать как по значению, так и по ссылке, в то
время как параметры сложных типов всегда передаются по ссылке. Для указания компилятору на
необходимость передачи параметра по ссылке, перед именем параметра ставится знак
амперсанда &.
Передача параметра по ссылке означает передачу адреса переменной, поэтому все изменения,
произведенные над переданным по ссылке параметром, сразу же отобразятся и в исходной
переменной. Используя передачу параметров по ссылке можно организовать возврат
одновременно нескольких результатов из функции. Чтобы предотвратить изменение переданного
по ссылке параметра, необходимо использовать модификатор const.
Таким образом, если входной параметр функции является массивом, объектом структуры или
класса, то в заголовке функции после типа переменной и перед ее именем ставится символ '&'.
Пример
class CDemoClass
{
private:
double m_array[];
public:
void setArray(double &array[]);
};
//+------------------------------------------------------------------+
//| заполнение массива |
//+------------------------------------------------------------------+
void CDemoClass::setArray(double &array[])
{
if(ArraySize(array)>0)
{
ArrayResize(m_array,ArraySize(array));
ArrayCopy(m_array, array);
}
}
В вышеприведенном примере объявлен класс CDemoClass, который содержит приватный член -
массив m_array[] типа double. Объявлена функция setArray(), в которую по ссылке передается
массив array[]. Если заголовок функции написать без указания передачи по ссылке, т.е. убрать
знак амперсанда, то при попытке компиляции такого кода будет выдано сообщение об ошибке.
Несмотря на то, что массив передается по ссылке, мы не можем произвести присвоение одного
массива другому. Необходимо сделать поэлементное копирование содержимого массива-
источника в массив-приемник. Наличие символа & для массивов и структур при передаче в
качестве параметра функции является обязательным при описании функции.
Ключевое слово this
Переменная типа класса (объект) может передаваться как по ссылке, так и по указателю.
Указатель как и ссылка служит для того, чтобы получать доступ к объекту. После объявления
Основы языка
© 2000-2011, MetaQuotes Software Corp.
86
указателя объекта необходимо применить к нему оператор new для его создания и
инициализации.
Зарезервированное слово this предназначено для получения ссылки объекта на самого себя,
доступной внутри методов класса или структуры. this всегда ссылается на объект, в методе
которого используется, а выражение GetPointer(this) даёт указатель объекта, членом которого
является функция, в которой осуществлен вызов функции GetPointer(). В MQL5 функции не могут
возвращать объекты, но разрешено возвращать указатель объекта.
Таким образом, если необходимо, чтобы функция вернула объект, то мы можем вернуть
указатель этого объекта в виде GetPointer(this). Добавим в описание класса CDemoClass функцию
getDemoClass(), которая возвращает указатель объекта этого класса.
class CDemoClass
{
private:
double m_array[];
public:
void setArray(double &array[]);
CDemoClass *getDemoClass();
};
//+------------------------------------------------------------------+
//| заполнение массива |
//+------------------------------------------------------------------+
void CDemoClass::setArray(double &array[])
{
if(ArraySize(array)>0)
{
ArrayResize(m_array,ArraySize(array));
ArrayCopy(m_array,array);
}
}
//+------------------------------------------------------------------+
//| возвращает собственный указатель |
//+------------------------------------------------------------------+
CDemoClass *CDemoClass::getDemoClass(void)
{
return(GetPointer(this));
}
Структуры не имеют указателей, к ним нельзя применять операторы new и delete, и нельзя
использовать GetPointer(this).
Смотри также
Указатели объектов, Создание и уничтожение объектов, Область видимости и время жизни
переменных
Основы языка
© 2000-2011, MetaQuotes Software Corp.
87
Операции и выражения
Некоторым символам и символьным последовательностям придается особое значение. Это - так
называемые символы операций, например:
+ - * / % символы арифметических операций
&& || символы логических операций
= += *= символы операций присваивания
Символы операций используются в выражениях и имеют смысл тогда, когда им даны
соответствующие операнды. Также особое значение придается знакам препинания. Знаки
препинания включают круглые скобки, фигурные скобки, запятую, двоеточие и точку с запятой.
Символы операций, знаки препинания и пробелы служат для того, чтобы отделять элементы
языка.
В данном разделе рассматриваются следующие темы:
Выражения
Арифметические операции
Операции присваивания
Операции отношения
Логические операции
Побитовые операции
Другие операции
Приоритеты и порядок операций
Основы языка
© 2000-2011, MetaQuotes Software Corp.
88
Выражения
Выражение состоит из одного или нескольких операндов и символов операций. Может
записываться в несколько строк.
Примеры:
a++; b = 10; // несколько выражений расположены на одной строчке
//--- одно выражение разбито на несколько строк
x = (y * z) /
(w + 2) + 127;
Выражение, заканчивающееся точкой с запятой (;), является оператором.
Смотри также
Приоритеты и порядок операций
Основы языка
© 2000-2011, MetaQuotes Software Corp.
89
Арифметические операции
К арифметическим относятся аддитивные и мультипликативные операции:
Сумма величин i = j + 2;
Вычитание величин i = j - 3;
Изменение знака x = - x;
Умножение величин z = 3 * x;
Частное от деления i = j / 5;
Остаток от деления minutes = time % 60;
Добавление 1 к значению переменной i++;
Добавление 1 к значению переменной ++i;
Вычитание 1 от значения переменной k--;
Вычитание 1 от значения переменной --k;
Операция инкремента и декремента применяются только к переменным, к константам не
применяются. Префиксныe инкремент (++i) и декремент (--k) применяются к переменной
непосредственно перед использованием этой переменной в выражении.
Постфиксные инкремент (i++) и декремент (k--) применяются к переменной сразу после
использования этой переменной в выражении.
Примеры:
int a=3;
a++; // верное выражение
int b=(a++)*3; // неверное выражение
Смотри также
Приоритеты и порядок операций
Основы языка
© 2000-2011, MetaQuotes Software Corp.
90
Операции присваивания
Значением выражения, в которое входит операция присваивания, является значение левого
операнда после присваивания:
Присваивание значения x переменной y у = x;
Следующие операции объединяют арифметические или побитовые операции с операцией
присваивания:
Увеличение значения переменной у на x у += x;
Уменьшение значения переменной y на x y -= x;
Умножение значения переменной y на x y *= x;
Деление значения переменной y на x y /= x;
Остаток от деления значения переменной y на x y %= x;
Сдвиг двоичного представления y вправо на x бит y >>= x;
Сдвиг двоичного представления y влево на x бит y <<= x;
Побитовая операция И двоичных представлений y и x y &= x;
Побитовая операция ИЛИ двоичных представлений y и x y |= x;
Побитовая операция исключающее ИЛИ
двоичных представлений y и x y ^= x;
Побитовые операции производятся только с целыми числами. При выполнении операции
логический сдвиг представления y вправо/влево на x бит используются младшие 5 двоичных
разрядов значения x, старшие разряды отбрасываются, то есть сдвиг производится на 0-31 бит.
При выполнении операции %= (значение y по модулю x) знак результата совпадает со знаком
делимого.
В выражении оператор присваивания может присутствовать много раз. В этом случае обработка
выражения ведется справа налево:
y=x=3;
Сначала переменной x будет присвоено значение 3, затем переменной y будет присвоено значение
переменной x, то есть тоже 3.
Смотри также
Приоритеты и порядок операций