Новая версия платформы MetaTrader 5 build 2085: Интеграция с Python и массовые улучшения в тестере стратегий - страница 33

 

Планируется ли улучшение подсветки синтаксиса в редакторе?  Как минимум, нужна подсветка пользовательских типов.  Иначе плохо читается код в стиле ООП, сливается в сплошной чёрный цвет. Порой сразу и не разберёшь, где тип, а где переменная.  Можно сделать либо тем же цветом, что и встроенные типы, либо настраиваемый цвет (предпочтительней).

И ещё момент. Не всегда срабатывает подсветка макросов. В одной из веток я поднимал этот вопрос, оказалось что это действительно распространённая проблема.  Закономерности выявить не удалось.  Бывает, что в одной строке макрос подсвечивается, а в следующей - уже нет.  Или наоборот.

 

По поводу неявного оператора присваивания.

Я уже неоднократно обращал внимание на спорность существующей реализации, допускающей такое:

class A { int a; };

class B : A { int b; };

void OnStart()
{
  A a;
  B b;
  b = a; // Нет ошибки?
}

что является смысловой ошибкой, т.к. вместо присваивания (полной замены объекта) здесь происходит лишь частично замещение его внутренностей (класс A).  Это не соответствует сути оператора=.

Но это ещё цветочки.

Вот такой вариант тоже компилируется без проблем:

class A { int a; };

class B : public A { long b; };

class C : public A { double c; };

void f()
{
  B b;
  C c;
  b = c; // Нет ошибки?
}

Здесь уже присваивание между объектами совершенно разных классов. Происходит замещение некой общей внутренней части, что вообще не очевидно.  Иерархия наследований может быть значительно больше, и мы даже не поймём, что именно там замещается, видя такую запись. По смыслу она означает, что объект B будет полностью заменён содержимым объекта С,  а по факту получаем неизвестно что.   Зачем компилятор позволяет такое?  

Всё это вынуждает либо полностью запрещать оператор= во всех классах, либо как-минимум делать его protected.  Т.е. реализация неявного оператора в таком виде - это медвежья услуга.  Лучше бы он вообще был запрещён, как в прежние времена, ошибок будет меньше.

P.S.  За примерами из реальной жизни далеко ходить не надо. Достаточно взять даже стандартную библиотеку, где все классы наследуются от CObject.  Попробуйте например объекту CTrade присвоить CChart.  Всё "прекрасно" присвоится!  Компилятор даже не заикнётся.  А как это повлияет на работу вашего кода - остаётся только гадать… 

 
threat:

Важное уточнение - почти все объекты получены не нажатием кнопки на меню, а выделением и копированием с нажатой CTRL. Таким образом они почти все являются потомками друг друга. Возможно здесь наследуется что-то лишнее или не отображается у потомка свойство, которое было активно у предка. Например, выделение. 

Посмотрите их имена.

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

 
Alexey Navoykov:

По поводу неявного оператора присваивания.

Я уже неоднократно обращал внимание на спорность существующей реализации, допускающей такое:

что является смысловой ошибкой, т.к. вместо присваивания (полной замены объекта) здесь происходит лишь частично замещение его внутренностей (класс A).  Это не соответствует сути оператора=.

Но это ещё цветочки.

Вот такой вариант тоже компилируется без проблем:

Здесь уже присваивание между объектами совершенно разных классов. Происходит замещение некой общей внутренней части, что вообще не очевидно.  Иерархия наследований может быть значительно больше, и мы даже не поймём, что именно там замещается, видя такую запись. По смыслу она означает, что объект B будет полностью заменён содержимым объекта С,  а по факту получаем неизвестно что.   Зачем компилятор позволяет такое?  

Всё это вынуждает либо полностью запрещать оператор= во всех классах, либо как-минимум делать его protected.  Т.е. реализация неявного оператора в таком виде - это медвежья услуга.  Лучше бы он вообще был запрещён, как в прежние времена, ошибок будет меньше.

P.S.  За примерами из реальной жизни далеко ходить не надо. Достаточно взять даже стандартную библиотеку, где все классы наследуются от CObject.  Попробуйте например объекту CTrade присвоить CChart.  Всё "прекрасно" присвоится!  Компилятор даже не заикнётся.  А как это повлияет на работу вашего кода - остаётся только гадать… 

Спасибо за сообщение.

Мы в курсе данной особенности/спорности MQL и планируем убрать неявное приведение к предку при вызове операторов (как в C++)

 
Ilyas:

Спасибо за сообщение.

Мы в курсе данной особенности/спорности MQL и планируем убрать неявное приведение к предку при вызове операторов (как в C++)

Ок.  Кстати можно наверно было бы оставить одно исключение: когда размер целевого класса совпадает с размером предка, т.к. наследник не имеет дополнительных полей.  В таком случае он физически эквивалентен предку:

struct A { double a; };

struct B : A   // Фактически эквивалентен A
{ 
  string ToString() const { return (string)a; }
};

В таких случаях присваивание не несёт каких-либо проблем.

 
Ilyas:

планируем убрать неявное приведение к предку при вызове операторов (как в C++)

Наверное имеется ввиду только operator=(...) - который не наследуется, потому что допустим operator+(...) и другие компилируются в С++ нормально

#ifdef __cplusplus
class A { public:
        void operator +(const A&) {}
};
class B : public A {};
class C : public A {};
void OnStart()
{
        B b;
        C c;
        b + c;
}
#endif
 
Alexey Navoykov:

Ок.  Кстати можно наверно было бы оставить одно исключение: когда размер целевого класса совпадает с размером предка, т.к. наследник не имеет дополнительных полей.  В таком случае он физически эквивалентен предку:

В таких случаях присваивание не несёт каких-либо проблем.

Можно пойти дальше... и сделать исключение также для случая, когда A::operator=(...) определен явно.

class A { public:
        void operator =(const A&) {}
};
class B : public A {};
class C : public A {};
void OnStart()
{
        B b;
        C c;
        b = c; //а почему бы и нет?
}

Формально вызов operator=(...) не обязательно означает присваивание и если он определен явно, то пользователь знал что делал и вложил в него какой то свой смысл, отличный от умолчания

 
A100:

Можно пойти дальше... и сделать исключение также для случая, когда A::operator=(...) определен явно.

Формально вызов operator=(...) не обязательно означает присваивание и если он определен явно, то пользователь знал что делал и вложил в него какой то свой смысл, отличный от умолчания

Лучше для этих целей попросить, чтобы ввели в язык новый спецификатор using для методов классов, появившийся в последнем стандарте С++.  Он позволяет легко наследовать конструкторы, операторы, и всё прочее:

class A { public:   A(int a=0) { } }; class B : public A { public:   using A::A;         // Наследуем все конструкторы класса A   using A::operator=; // Наследуем оператор копирования }; B b(2); void f() { A a; b=a; }

Мега-удобная штука.  Особенно для конструкторов.  Также с её помощью можно менять видимость родительских полей и методов.

 
Alexey Navoykov:

И ещё момент. Не всегда срабатывает подсветка макросов. В одной из веток я поднимал этот вопрос, оказалось что это действительно распространённая проблема.  Закономерности выявить не удалось.  Бывает, что в одной строке макрос подсвечивается, а в следующей - уже нет.  Или наоборот. 

Вот закономерность

 попробовал сейчас - работает (закономерность)

 

OFF TOP

Сегодня перестало работать мобильное приложение МТ5 для IOS билд 1171 на старом Айфоне (не коннектится даже к демо серверу MQ, пишет "connection lost").

Поддержка прекращена?

Причина обращения: