![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
ps: не забывайте, что мы профессиональные программисты и у многих из нас по 15-20 лет опыта именно в программировании.
Сам по себе срок не означает уровня. Не зря тут люди удивляются.
C++ подобный язык без exception handling - ещё те грабельки.
Код возврата?
Зачем тогда было создавать урезанный С++ ?
Вполне хватило бы доработки до C.
Добавили бы структур, которых так не хватало, условное выражение и нормальный return, и - всё.
Условное выражение добавили, return сделали нормальный, но вместо добавления структур зачем-то решили доусложнять до C++.
Интересно как вы разрулите векторный вызов ( new CObject[100] )?Советую Вам использовать отдельную функцию инициализации, вместо сложного конструктора.
Сам по себе срок не означает уровня. Не зря тут люди удивляются.
C++ подобный язык без exception handling - ещё те грабельки.
Вот-вот. Такое впечатление, что все указанные годы варились в каком-то собственном соку, и понятия не имеют, что делается в мире. А там в принципе уже десятки других программистских фирм (наверно они полные кретины?) наваяли свои собственные программы-платформы со встроенными языками, и везде, где язык поднимался до уровня ООП, поддерживались эксепшены. Ладно меня можно не слушать, ну так хоть изучите то, что по вашей теме уже делалось и какие решения принимались, проверенные временем. Не надо считать себя умнее других. Если просто нет возможности сделать (ресурсов не хватает или еще чего), так и напишите, а не сочиняйте вздорные отписки. Не надо считать всех программистов ламерами, и Эйнштейн может ошибиться, и ваша задача, как поставщиков платформы, сделать в ней контроль ошибок на уровне. Пенять на программиста, дескать он нифига не проверяет - последнее дело, особенно учитывая, что Вы сами не желаете централизованно сделать то же самое.
P.S.Можете не отвечать. Я эту ветку больше не читаю. Надоело доказывать, что 2+2=4. ;-)
Интересно как вы разрулите векторный вызов ( new CObject[100] )?В языке C++ не вижу никаких проблем в разруливании и вектрного вызова. Обычно я так не делаю, но в данном случае приведу пример программы на C++, демонстрирующей отсутствие подобных проблем. Извиняюсь за длинноватый код, но иначе трудно продемонстрировать. Я постарался его ужать.
Статический метод test() принимает количество объектов, которое будет создано прежде, чем конструктор выбросит исключение.
Программа выдаёт следующий отчёт о деталях своей работы:
Легко видеть, что в первом ("нормальном") случае все объекты вектора успешно создаются, каждый элемент отрабатывает (метод work(), строка "I am working"), потом все объекты штатно уничтожаются. По распечатке значения this можно видеть, какой объект - какой, что в каком порядке происходит.
Во втором случае, при исполнении в функции test() кода "CObject *p = new CObject[v_size];" во время создания третьего элемента вектора из конструктора выбрасывается исключение.
Обращаю внимание, что тот код в функции test(), который первым получит после этого события управление, находится в блоке "catch(int i)".
Это значит, что работа со всем вектором объектов отменится, даже если хотя бы один из объектов не сконструируется доконца.
Вместо этого управление получит код в блоке "catch(int i)", ответственный за действия в случае неудачи. Обращаю внимание, что этот код не выполняется в случае штатной работы, как это видно по отчёту программы в случае вызова test(3) из main().
Вот тут люди жаждут позиции позакрывать в случае нештатной ситуации - пожалуйста.
Что же происходит между выбросом исключения и конструктора третьего объекта и получением управления блоком "catch(int i)"?
Как видно по отчёту программы, все доконца сконструированные объекты, то есть, первый и второй объекты уничтожаются в порядке, обратном их созданию с помощью вызова деструктора, потому что компилятор C++ вставил соответствующий код.
Все НЕдоконца сконструированные объекты, то есть, третий объект, не уничтожаются. Они не созданы, потому что их конструктор, будучи вызван, не вернул управление. И это неуничтожение НЕдоконца сконструированных объектов тоже гарантируется соответствующим кодом, вставляемым компилятором C++.
Далее, был вызван "CObject::operator delete[]()" - причём, именно парный соответствующему "CObject::operator new[]()", - и тоже только благодаря тому, что компилятор C++ вставил соответствующий код. Только после этого управление передаётся в блок "catch(int i)".
Итак, в случае штатной ситуации всё работает в соответствии с кодом, находящимся в блоке "try", блоки "catch()" не исполняются.
В случае же нештатной ситуации в работу вступают автоматизмы C++, гарантирующие (при их правильном применении) неисполнение кода, который иначе работал бы с (полу)несозданными объектами и приводил к так называемым "крешам". Эти автоматизмы гарантируют откат в смысле удаления полностью сконструированных объектов, выходящих из области видимости, освобождение выделенной памяти и передачу управления в правильное место обработки возникшей нештатной ситуации.
Вам всё ещё интересно?
Надеюсь, пример объясняет, почему нет проблемы и в случае вектора объектов.
Кстати, можно вектор объектов заменить на "невектор", то есть, на один объект - поведение кода (естественно, без пробежки по вектору в цикле for, а с вызовом методов одного объекта и с соответствующей заменой new и delete на невекторные версии) в смысле реакции на исключения останется тем же самым.
Я полагаю, что разработчики системы, в которой используется C++-подобный язык, должны иметь очень глубокое понимание самого языка C++, его механизмов и философии, чтобы смочь грамотно спроектировать этот C++-подобный язык, понимая, что отделимо от него при таком-то его задании как подмножество C++, а что - нет.
Что теперь делать?
Вводить обработку исключений (возможно, в будущем) или выбросить конструирование?
Оставить, всё как есть?
Кстати, язык C++ - сложен и зачастую неподъёмен даже для профессиональных программистов. Это значит, что грамотно пользоваться они им не умеют.
Вот C - другое дело. Этот - многим по силам. Чтобы грамотно пользоваться, я имею ввиду. Хватило бы его вполне в терминале.
Интересно как вы разрулите векторный вызов ( new CObject[100] )?Советую Вам использовать отдельную функцию инициализации, вместо сложного конструктора.
А теперь рассмотрим то же самое, но с позиций MQL5.
Отдельную функцию инициализации использовать можно, но вызывать-то её придётся руками!
А вызов конструктора компилятор (особенно, отлаженный компилятор) уж точно не забудет вставить. Стоит только объявить перенную-объект - и конструктор обязательно будет вызван. Ну не забудет компилятор этого сделать!
А деструктор? Руками - запросто забыть можно. Опыт это показывает. А компилятор MQL5 уж точно не забудет заботливо вставить соответствующий код при завершении времени жизни переменной-объекта.
И как мне разруливать векторные вызовы? После строки объявления вектора пробегаться в цикле по всем его объектам, вызывая для каждого функцию инициализации?
Вот больше делать нечего, как всякие автоматизмы руками дублировать. Конструкторы-то тогда для чего?
А если у меня объект (A) состоит из многих других объектов (B, C, D), то я должен из его функции инициализации (A::init()) не забыть вызвать функции инициализации (B::init(), C::init(), D::init()) каждого из объектов, из которых он состоит?
А если я добавлю ещё один объект (E) в A, то как мне не забыть модифицировать A::init(), вызвав оттуда E::init()?
Добавим сюда наследование - инициализацию подобъектов тоже руками выполнять?
И код отката в случае невозможности дальнейшей инициализации объекта - тоже самому писать?
А когда тогда собственно программированием поставленной задачи заниматься?
Зачем в MQL5 существует автоматизм конструкторов/деструкторов, если пользоваться по-человечески этим автоматизмом нельзя?
Вполне хватило бы C-подобного языка со структурами, раз уж самому надо следить за инициализацией и деинициализацией.
Хороши грабельки - выбросить обработку исключений...
Сразу оговорюсь, что MQL5 как и MQL4 является прикладным языком, и программы, на нем написанные, полноценными не являются.
Поэтому всерьез сравнивать их с С и тем более с С++ это бред. Но почему-то про это постоянно забывают.
simpleton :
Отдельную функцию инициализации использовать можно, но вызывать-то её придётся руками!
И что? Религия не позволяет? Неужели ни разу не видели в C++ коде метод SetHandler(...)? Тем более защиту от дурака прикрутить -- 2 пальца об асвальт.
Да, это проблема, но она вполне решаема. Имхо, отсутствие виртуального и множественного наследования -- гораздо бОльшая проблема.
Что мешает пользоваться именно таким набором и забить на классы?
Хороши грабельки - выбросить обработку исключений...
Необходимость в исключениях в подконтрольном коде вообще под вопросом.
Может, шаблоны еще вспомнить?
Дальше, пример. Притянутый за уши по самое никуда. ТАК исключения использовать НЕЛЬЗЯ.
Кстати, язык C++ - сложен и зачастую неподъёмен даже для профессиональных программистов. Это значит, что грамотно пользоваться они им не умеют.
Судя по всему, Вы именно из этой категории.
Сразу оговорюсь, что MQL5 как и MQL4 является прикладным языком, и программы, на нем написанные, полноценными не являются.
Поэтому всерьез сравнивать их с С и тем более с С++ это бред. Но почему-то про это постоянно забывают.
Точно... Хороший язык. О таких вещях раньше и мечтать было нельзя.
А теперь и наследование, виртуальные функции.
Разработчики могли вообще сделать расширенный MQL4.
Мне очень понравился MQL5. (спасибо). Очень многое упростилось.
За отладчик отдельное спасибо.
А без исключений можно обойтись.
Человек по натуре такое существо. Будем сражаться, добиваться,
а когда получим желаемое, то возьмем весь код индикатора в один try,
а в catch напишем Print("Error "...) и скажем: "Вот, с исключениями другое дело". :)
Снова возвращась к "проблеме" деления на 0.
(т.н. zero divide )
Неужели это принципильное условие???
Вот сегодня, из-за частого появления случаев в параметрах 0 пришлось лопатить
и уж простите тулить лажу... иного слова не знаю... если на 0.00000001 можно, а на 0 нельзя.
Ну и пусть себе вместо истиного расчёта всё тот-же 0, чем галиматью в виде например бешеных процентов...
ИЕ.
Сразу оговорюсь, что MQL5 как и MQL4 является прикладным языком, и программы, на нем написанные, полноценными не являются.
Поэтому всерьез сравнивать их с С и тем более с С++ это бред. Но почему-то про это постоянно забывают.
И что? Религия не позволяет? Неужели ни разу не видели в C++ коде метод SetHandler(...)? Тем более защиту от дурака прикрутить -- 2 пальца об асвальт.
Да, это проблема, но она вполне решаема. Имхо, отсутствие виртуального и множественного наследования -- гораздо бОльшая проблема.
Что мешает пользоваться именно таким набором и забить на классы?
Необходимость в исключениях в подконтрольном коде вообще под вопросом.
Может, шаблоны еще вспомнить?
Дальше, пример. Притянутый за уши по самое никуда. ТАК исключения использовать НЕЛЬЗЯ.
Судя по всему, Вы именно из этой категории.
В чём неполноценность программ MQL5? Нельзя объектник получить и слинковать с ним свою программу или прилинковать статически к программе MQL5 объектник, полученный трансляцией с C++? Нет ключевого слова asm?
Вот тогда именно в этом смысле и следует понимать бредовость сравнения MQL5 и C++. Но я же не эти особенности сравниваю.
А по части устройства самого языка в сравнении никакого бреда нет. Что за глупые логические ошибки в собственных рассуждениях? В надежде, что не замечу?
Дело не в религии. Я для кого объяснял, что происходит дублирование механизма инициализации/деинициализации, причём именно ручное дублирование?
Для кого объяснял, что это является дополнительным источником ошибок и нивелирует преимущество, предоставляемое автоматизмом конструкторов/деструкторов?
Для кого объяснял, что в случае сложных объектов это ручное дублирование тоже становится сложным, и допустить ошибку в нём становится намного проще?
И для кого объяснял, что отлаженный компилятор будет безошибочно строить логику инициализации/деинициализации, какими бы сложными не были объекты, и можно будет сосредоточиться на собственно программировании задачи и не отвлекаться на не связанные с ней вещи, что положительно повлияет на качество этого программирования и на количество допущенных при этом ошибок (их будет меньше)?
Апелляции к тому, что так пишут, - странны, по крайней мере. Мало ли чего делают кое-как?
К тому же, механизм исключений способствует разделению кода, реализующего алгоритм - он сосредотачивается, в основном, в блоках try, и кода, обрабатывающего ошибки - он сосредотачивается в блоках catch, что дополнительно уменьшает вероятность допущения ошибок, поскольку код реализации алгоритма становится меньше "разбавлен" логикой обработки ошибок.
Вот не надо ещё долго никакого виртуального и множественного наследования, пока дизайн языка находится в противоречивом, недоделанном состоянии.
Это бы поднять, - то, что есть. Какие шаблоны, когда то, что есть, уже на костылях ещё в стадии дизайна?
Необходимость в исключениях ещё больше вырастет, когда введут (уже обещали) перегрузку операторов. По той же самой причине вырастет необходимость.
Пользоваться подмножеством языка MQL5, соответствующему языку C, теоретически ничто не мешает.
Практически же - качество языка будет хуже, поскольку усилия одного и того же количества разработчиков будут сосредоточены на поддержке не только и не столько этого подмножества, сколько на поддержке той части языка, которая соответствует функциональности надмножества C++.
Вот, к примеру, первый же минимальный тест, который пришёл мне в голову, выявил bug MQL5 в реализации инициализации/деинициализации сложных объектов. То есть, и там ещё всё находится в стадии альфа. И разработчики вынуждены будут прилагать усилия для поддержки этой части, чтобы сначала вывести язык в стадию бета, а потом, хочется надеяться, и в стадию релиза. Кстати, успеют ли до чемпионата 2010 года?
Второе практическое отличие - психологический дискомфорт от того, что механизм, вроде бы, и есть, но пользоваться им нельзя, поскольку не работает, как положено.
Пример - не притянутый за уши, пример демонстрирует, причём, очень наглядно, как работают механизмы инициализации/деинициализации, в том числе, в случае исключения для случая посложнее одиночного объекта.
Почему так исключения использовать нельзя? Стандарт C++ запрещает?
Где аргументы-то? Хотя бы для того, чтобы понять мысль, что имелось ввиду под ТАК и почему НЕЛЬЗЯ?
Заметили, что я аргументирую свои высказывания, причём стараюсь это сделать так, чтобы любой мог проверить эти аргументы?
У вас какие-то проблемы с логикой.
Человек, который в состоянии продемонстрировать работу механизмов C++ и объяснить их смысл и значение за счёт того, что хорошо понимает и разбирается в языке, именно поэтому и не умеет им грамотно пользоваться?
Логика в стиле - "Всё учёные - неучи, потому что они - учёные"?
Ну, и насколько тогда близко к истине ваше утверждение, основанное на подобной логике?
Снова возвращась к "проблеме" деления на 0.
(т.н. zero divide )
Неужели это принципильное условие???
Вот сегодня, из-за частого появления случаев в параметрах 0 пришлось лопатить
и уж простите тулить лажу... иного слова не знаю... если на 0.00000001 можно, а на 0 нельзя.
Ну и пусть себе вместо истиного расчёта всё тот-же 0, чем галиматью в виде например бешеных процентов...
ИЕ.
В парадигме "если возникла проблема, то её следует 'замять', даже за счёт достоверности вычислений" данная проблема решается примерно так:
Пользоваться значком "/" для операции деления запрещается, вместо этого используется следующая функция:
Значение по умолчанию для третьего параметра выбрать таким, чтобы в большинстве случаев устраивало, и можно было вызывать функцию div(), передавая ей лишь два параметра:
и лишь в редких случаях задавать третий, когда требуется другое значение минимально допустимого делителя.
Если же нужно возвращать 0 в случае 'нехорошего' делителя, то можно использовать, например, такую функцию: