Обновление платформы MetaTrader 4 билд 625: Журналы в MetaTrader Market и новый MetaViewer - страница 34

 
simpleton:

Не универсально:

1. "Функция ZeroMemory() не применима для классов с защищенными членами или наследованием".

2. "Для любых массивов, не защищенных модификатором const, производится обнуление всех элементов".

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


Это всё верно, но там вопрос был об обнулении структуры.
 
Alexey_74:

Так и есть.

Текст индюка не меняем:

А вот текст длл меняем - double на RateInfo

Вот и срослось

Колонка open стала, как родной братец.


Спасибо за инфу, будем знать. )
 
simpleton:

Вместо OnCalculate() с портянкой параметров подошла бы OnCalculate() с тремя параметрами, где третий параметр - "const MqlRates &[]".

RickD:

Поддерживаю!


А я - нет. Писать в теле функции "open[i]" - удобнее и читабельнее, чем "Rates[i].open". Колонка параметров мне не мешает.
[Удален]  
Spy:

Это всё верно, но там вопрос был об обнулении структуры.
Хорошо, если взять именно структуру и проверить положение дел на практике. Для случая, когда объект - константный:
#property strict

void OnStart() {
  struct S {
    int i;
    int j;
  };

  const S s = { 1, 2 };

  Print("1: s.i = ", s.i, ", s.j = ", s.j);
  ZeroMemory(s);
}

Попытка скомпилировать скрипт приводит к следующему сообщению об ошибке:

's' - constant variable cannot be passed as reference   1.mq4   12      14

Соответственно, как минимум для данного случая, "инициализация" (а на самом деле, присвоение полям нулевых значений) при помощи функции ZeroMemory() не годится.

Если же закомментировать вызов ZeroMemory(), то компиляция - успешна, и в логе видно, что (настоящая) инициализация константного объекта осуществилась также успешно.

20:42:09 Script 1 EURUSD,H1: loaded successfully
20:42:09 1 EURUSD,H1: initialized
20:42:09 1 EURUSD,H1: 1: s.i = 1, s.j = 2
20:42:09 1 EURUSD,H1: uninit reason 0
20:42:09 Script 1 EURUSD,H1: removed

Для случая же, когда сам объект - неконстантный, а константны лишь некоторые из его полей:

#property strict

void OnStart() {
  struct S {
    int i;
    const int j;
  };

  S s = { 1, 2 };

  Print("1: s.i = ", s.i, ", s.j = ", s.j);
  ZeroMemory(s);
  Print("2: s.i = ", s.i, ", s.j = ", s.j);
}

Компиляция проходит успешно, и появляется возможность иметь удовольствие наблюдать в логе, какая вакханалия творится с КОНСТАНТНЫМ полем:

20:40:07 Script 1 EURUSD,H1: loaded successfully
20:40:07 1 EURUSD,H1: initialized
20:40:07 1 EURUSD,H1: 1: s.i = 1, s.j = 2
20:40:07 1 EURUSD,H1: 2: s.i = 0, s.j = 0
20:40:07 1 EURUSD,H1: uninit reason 0
20:40:07 Script 1 EURUSD,H1: removed

После (настоящей) инициализации поля имеют правильные значения. По сути своей, по определению, поле s.j теперь не может быть изменено до самого конца жизни переменной, - в этом, ведь, вся суть квалификатора const, и любые попытки программиста сделать это должны на корню пресекаться компилятором.

В случае прямых попыток присвоить какое-нибудь значение полю s.j так и происходит, - компилятор выдаёт ошибку и не компилирует скрипт.

Однако, в данном случае, при использовании функции ZeroMemory() для "инициализации", она доблестно "выжгла" значение КОНСТАНТНОГО поля объекта.

Это - однозначный bug дизайна языка. Ведь настоящая инициализация происходит один раз при объявлении (определении) объекта, и после этого компилятор гарантирует пресечение попыток программиста по ошибке изменить значение константных полей, а "инициализация" при помощи ZeroMemory() может быть выполнена многократно в течение всего срока жизни переменной, и компилятор ничего не скажет о том, что право константных полей на неизменность своего значения в течение всего срока жизни переменной теперь грубо попирается, причём это может происходить многократно, сколько угодно раз в течение жизни переменной. А программист об этом не только не знает, но и не догадывается. :)

Источник потенциальных глюков готов. Это - ещё одна причина, по которой нельзя использовать функцию ZeroMemory().

[Удален]  
Spy:

А я - нет. Писать в теле функции "open[i]" - удобнее и читабельнее, чем "Rates[i].open". Колонка параметров мне не мешает.
Поскольку в языке имеется перегрузка функций, можно было бы позволить программисту выбирать любую из двух (или больше, если есть смысл в большем количестве) версий OnCalculate() с единственным условием, чтобы в файле исходника индикатора использовалась только одна из них, иначе исполнительной системе неясно будет, какую версию следует использовать для вызова индикатора.
[Удален]  
Вопрос к разработчикам. Можно ли увеличить длину комментария ордера с 32 до 64 символов? 32 символа бывает чуть чуть не хватает для хранения 2 идентификаторов типа int + немного форматирования.
 
Spy:

А я - нет. Писать в теле функции "open[i]" - удобнее и читабельнее, чем "Rates[i].open". Колонка параметров мне не мешает.

А чем тебя не устраивает писать Open[i]?
 

Хочу получить ответ и рекомендации от разработчиков.

Уважаемые друзья, покажите, расскажите, ткните носом где можно учить классы, структуры, и по каким материалам ..

Примеры в терминале мт4 пока что сложны и не понятны.

Может Вы планируете учебник создать или статью большую так как те статьи которые есть на данном ресурсе не понятны и не охватывают все возможности ООП...

От желания изучить ООП я записался в клуб и Вы знаете небольшие успехи есть, но хочется большего ...

[Удален]  
simpleton:
Хорошо, если взять именно структуру и проверить положение дел на практике. Для случая, когда объект - константный:

Попытка скомпилировать скрипт приводит к следующему сообщению об ошибке:

...


Это я, Spy. Переименовался, чтобы был одинаковый ник с форумом MQL5 (там ник Spy оказался занят). Спрашивал админа, возможно ли просто изменить здесь ник, но ответом была тишина... То ли нельзя, то ли послал молча. ))

Вы вопрос читали, на который я отвечал? ) Там ничего не было про константные структуры, которые вообще нельзя изменить (потому что константные), соответственно и обнулить - тоже. Мой ответ никак не претендовал на универсальность, он относился к конкретному случаю, о котором спросил VOLDEMAR: как попроще инициализировать нулями структуру сразу после создания. В его случае это проще всего сделать прямым обнулением памяти.

Однако, в данном случае, при использовании функции ZeroMemory() для "инициализации", она доблестно "выжгла" значение КОНСТАНТНОГО поля объекта.

Это - однозначный bug дизайна языка.

В студии:

#include "stdafx.h"
#include <Windows.h>
#include <iostream>

struct S
{
        int i;
        const int j;
};

int main()
{
        S s = { 1, 2 };

        std::cout << "Before ZeroMemory. i = " << s.i << ", j = " << s.j << "\n";

        ZeroMemory(&s, sizeof(S));

        std::cout << "After ZeroMemory. i = " << s.i << ", j = " << s.j << "\n\n";

        system("Pause");

        return 0;
}

Результат:

Впрочем, я согласен, что это неправильно.

[Удален]  
Alexey_74:

А чем тебя не устраивает писать Open[i]?

Time[], Open[], High[], Low[], Close[], Volume[] - устаревшие таймсерии, в MQL5 их нет. Не исключено, что и в четвёрке со временем уберут. Поэтому лучше от них отвыкать.