Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Лично я использую статические функции для "обслуживающих" процедур, которые относятся к классу, однако, не требуют доступа к нестатическим членам. Ну, скажем, функции преобразования перечислений. Или, скажем, функции, работающие только со статическими членами класса - очень удобно, когда есть одна статическая переменная, доступная для всех объектов данного класса, соответственно, для работы с ней нередко удобны как раз статические функции.
Вот мне и хочется один раз пересчитать статические данные класса, которыми пользуются все экземпляры, а не считать в каждом экземпляре. Но для каждого производного класса эта функция своя.
У меня есть базовый класс робота, ...
Да, для объединения в одном советнике многих экземпляров торговых роботов или стратегий использование такого подхода - самое то. Без виртуальных функций сделать такое можно только гораздо сложнее и некрасивее.
Не хватает статических виртуальных функций, чтобы для экземпляров каждого производного класса лишь один раз производить все общие действия (расчёт индикаторов, копирование их данных, прочие вычисления), но это симулируется через указатели на функции.
Вот тут не понятно, что за статические виртуальные функции могли бы как-то помочь. Не слышал про подобные механизмы в ООП. Но их можно вполне реализовать и с имеющимися возможностями. Можно сделать в классе статические массивы для буферов индикаторов и статическую логическую переменную-флаг. На каждом тике флаг сбрасывается извне. Затем каждый робот вызывает метод получения данных индикатора. Внутри этого метода проверяется, если флаг сброшен, то статический буфер пересчитывается/загружается/пополняется и флаг устанавливается. Если же флаг уже установлен, это значит, что какой-то другой экземпляр робота уже заставил индикатор обновить данные в статическом буфере на этом тике, поэтому они берутся оттуда.
А вообще лучше вынести все индикаторы в отдельный класс, который будет следить за созданием и пополнением буферов всех используемых в советнике индикаторов. Планирую сделать это в будущем. Пока сделал подобную вещь для котировок по разным символам. Есть статический объект, к которому все роботы обращаются за ценами. Если это первое обращение для данного символа, то для него создаётся и добавляется в массив объект CSymbolInfo, ему обновляются котировки и этот объект отдаётся роботу. Если объект для такого символа уже был создан ранее, то он берется из массива и возвращается роботу по запросу. В начале тика все объекты CSymbolInfo из массива обновляют котировки для своих символов. А каждый из сотен роботов теперь не вызывает изнутри RefreshRates(), так как знает, что у запрошенного объекта CSymbolInfo цены и так свежие. Конечно, у такого подхода есть свои ограничения, но если они оказываются некритичными, то им вполне можно пользоваться.
А где проверка результата преобразования😄? Хотя, в рантайме терминал и так проверит указатель перед обращением к нему. Если из кода проверять указатель, то нужно что-то делать если передали не то, что ожидали. А из Compare "что-то делать" не сильно удобно и не сильно хочется. Даже эксепшин бросать мне не очень хотелось бы.
Владислав, Вы внимательны к деталям, спасибо за подсказку. Вот полная версия:
А эксепшн наверное можно сделать как-то так:
Если сравнение не произойдёт, то метод вернёт "-2".
Ещё пример использования виртуальных методов.
Упоминался как-то выше метод CObject::Compare(). Вот его полное определение:
Допустим, есть потомок класса CObject, в котором хранится статистика о торговом сигнале.
Допустим, что метод CSignalData::Compare() должен сравнивать 2 объекта сигналов по времени (m_dtime) - текущий и другой (задаётся как параметр метода - _ptr_other_sig). И тут есть нюанс. Сравнивать мы можем только объекты типа CSignalData. Но с другой стороны, нам нужно сохранить сигнатуру метода: тип параметра _ptr_other_sig должен оставаться как CObject*.
Как быть? ))
Это экзамен?
Как я понял из написанного Артёмом Тришкиным, метод Compare() вызывается из
Следовательно сравнение так влоб или нецелесообразно делать или просто неправильно.
Там что писал Артём последовательность такая:
Создаётся временный объект.
Ищется в списке и если не находится, добавляется в список.
Вот тут как раз вызывается Compare() в котором мы можем написать один, два или более критериев сравнения. То-есть можно поставить только m_dtime или m_dtime и m_symdol
Владислав, Вы внимательны к деталям, спасибо за подсказку. Вот полная версия:
А почему бы не сделать так:
Метод Compare с высокой вероятностью не будет вызываться в неизвестных обстоятельствах, его будут вызывать только методы сортировки и поиска. А там в сортируемом массиве или массиве для поиска лежат только указатели на одинаковый класс. Поэтому указатель в *_ptr_other_sig должен всегда успешно преобразовываться из CObject* в CSignalData*.
А почему бы не сделать так:
Наверное потому, что с dynamic_cast не упадет, а без него упадет (опять-же, не точно, я не проверял)
https://www.mql5.com/ru/docs/basis/types/casting#dynamic_cast
Я выше прилагал свою реализацию метода Compare:
То есть, внутри функции Compare - мы преобразуем указатель на CObject к указателю на реальный объект (наследник CObject), и проводим функции сравнения уже между этими указателями на реальные объекты.
Вот, как раз для этого и удобны виртуальные функции сравнения.
Это экзамен?
Как я понял из написанного Артёмом Тришкиным, метод Compare() вызывается из
Следовательно сравнение так влоб или нецелесообразно делать или просто неправильно.
Там что писал Артём последовательность такая:
Создаётся временный объект.
Ищется в списке и если не находится, добавляется в список.
Вот тут как раз вызывается Compare() в котором мы можем написать один, два или более критериев сравнения. То-есть можно поставить только m_dtime или m_dtime и m_symdol
Ну почему же сразу экзамен. Насколько понимаю, тут всё на добровольных началах: Вы копаете - мы закапываем, или мы копаем - Вы закапываете ))
Да, метод сравнения вызывается как правило из других. Но в целях упрощения примера я вызвал его напрямую. И тут неправильного ничего нет. Нужно отметить, что чаще всего метод используется в сортировках. Свои сортировки тоже можно писать...