Вопросы по ООП в MQL5 - страница 97

 
Alexey Volchanskiy #:

В учебнике куча ошибок, например:

--------------

Для автоматического объекта мы получали указатель, поставив амперсанд перед его именем (в данном контексте, символ амперсанда является оператором "взятия адреса"). Так, в следующем примере переменная p указывает на автоматический объект s.

Shape s;        // автоматический объект
Shape *p = &s;  // указатель на тот же объект
------------------
Никакие адреса амперсанд в MQL4/5 не возвращает, это не С++. В MQL в угоду безопасности нет работы с адресами, как и в C# и многих других языках. Самое смешное, что строчкой выше автор правильно пишет об этой особенности.

Лично для меня это, сейчас вообще не важно. Но если я споткнусь в подобной ситуации, я всегда могу перечитать ваше высказывание…

 
Alexey Viktorov #:

То-есть это можно применить как замену списку объектов?

Типа, имеем 5 валютных пар в работе советника, это будут, так сказать манагеры, открылась позиция манагер получил тикет позиции и другие её свойства. Если это так, то очень интересно, правда в реализации сложней чам список объектов.

Я затрудняюсь ответить. У меня нет опыта широкого применения паттернов подобных примеру из учебника. Я крайне редко разрабатываю мультивалютные советники и еще не создавал крутые продвинутые GUI (возможно что-то подобное может найти применение для GUI). Ну и необходимости в чем-то подобном у меня тоже не было:

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Вопросы по ООП в MQL5

Stanislav Korotky, 2024.11.20 16:27

сообщение группой расчетных алгоритмов процента выполнения конкретной задачи в планировщик задач

Хорошо, что Станислав присоединился к обсуждению, он компетентен в таких вопросах, в отличии от меня.

 
Vladislav Boyko #:


Хорошо, что Станислав присоединился к обсуждению, он компетентен в таких вопросах, в отличии от меня.

В компетентности его я не сомневаюсь. Просто от критики мало пользы…

 
Stanislav Korotky #:
Предложенная модификация с "преобразованием ссылки в указатель" делает код менее защищенным, так как ссылка не может быть испорчена, а указатель может. Кроме того, в вызывающем операторе для получения указателя нужно писать амперсанд (который вам же и не нравится), а вот ссылку мы получаем простым написанием имени объекта.

Я упростил код для того, чтобы он выглядел более понятным и читаемым для человека, который только изучает ООП. Я не предлагал модификации, я пытался объяснить что делает ваш код, переписав его более простым и наглядным способом. Следующие 2 строки делают одно и то-же:

owner = &t;
owner = GetPointer(t);

Но GetPointer более читаемо выглядит и его легко найти в документации.

В документации по this тоже GetPointer.

https://www.mql5.com/ru/docs/basis/types/this

//+------------------------------------------------------------------+
//| возвращает собственный указатель                                 |
//+------------------------------------------------------------------+
CDemoClass *CDemoClass::getDemoClass(void)
  {
   return(GetPointer(this));
  }
 
Stanislav Korotky #:
Предложенная модификация с "преобразованием ссылки в указатель" делает код менее защищенным, так как ссылка не может быть испорчена, а указатель может.

Я уже писал, что я преследовал цель сделать код проще, чтобы сосредоточиться на вашем паттерне.

Но при желании испортить можно что угодно:

class Manager;

class Element
  {
   Manager* owner;
public:
            Element(Manager &t) : owner(&t) { }
  };

class Manager {};

void OnStart()
  {
   Manager* m = NULL;
   Element e1(m); // OK
   Element e2((Manager*)NULL); // OK
  }
 
Vladislav Boyko #:

Я упростил код для того, чтобы он выглядел более понятным и читаемым для человека, который только изучает ООП. Я не предлагал модификации, я пытался объяснить что делает ваш код, переписав его более простым и наглядным способом. Следующие 2 строки делают одно и то-же:

Но GetPointer более читаемо выглядит и его легко найти в документации.

В документации по this тоже GetPointer.

Владислав, если даже я это понял, то вам нет необходимости разъяснять причины таких упрощений.

В общем спасибо Станиславу за такой учебник, за пример такой возможности, а вам спасибо за доходчивое объяснение.

На мой взгляд это говорит о настоящей пользе ООП. Всё что есть в СБ это пародия на ООП. Ну разве что, за некоторым исключением…

 
Stanislav Korotky #:
Один менеджер (одного типа, как в нашем примере) - это как раз самый частый случай, и он полон смыслов.

Если менеджер точно будет один на всю программу, то никакие указатели вообще не нужны, как и связанный с ними оверхед.

class Element
  {
public:
   string getMyName() const { return (typename(this)); }
   void   doMath();
  };

void Element::doMath(void)
  {
   const int N = 1000000;
   for(int i = 0; i < N; ++i)
      if(i % (N / 20) == 0)
         Manager::progressNotify(this, i * 100.0f / N);
  }

class Manager
  {
public:
   static void progressNotify(const Element &e, const float percent) { Print(e.getMyName(), "=", percent); }
  };

void OnStart()
  {
   Element arr[10];
   arr[5].doMath();
  }

И сам менеджер тоже теряет смысл. Его можно переименовать в ProgressNotifier и пускай там уведомляет себе.

Зачем делать громоздкий код для уведомлений? Для чего каждому элементу хранить копию указателя на менеджера, если менеджер только один на всю программу? Если что-то всегда будет только одно на всю программу, то его можно сделать полностью статическим и не морочить голову с хранением указателей.

Поэтому я и говорю, что ваш пример слишком абстрактный. Просто указатели ради указателей. Но, тем не менее, это не делает его плохим.

https://www.mql5.com/ru/book/oop/classes_and_interfaces/classes_pointers

void progressNotify(Element *e, const float percent)

Там ссылки достаточно для вызова методов.

 
Vladislav Boyko #:
Для чего каждому элементу хранить копию указателя на менеджера

Только если менеджеров может быть несколько экземпляров. Я не могу придумать другую причину для хранения копии указателя каждым элементом.

А для чего нужны несколько менеджеров, каждый из которых управляет собственным массивом элементов (которые, в свою очередь, могут общаться с оунером), лично мне придумать сложно. Это должно быть что-то большое, хитрое и масштабируемое. Собственно поэтому вы привели абстрактный пример (наверное) - что бы не добавлять в качестве примера большую программу.

 

Вообще, паттерн, при котором, объект владения владеет указателем на владельца, так себе решение, от лени я бы сказал. Тут, с ходу, две проблемы:

  1. Объект владения получает доступ ко всем публичным методам владельца. В принципе, бизнес-логики это фиолетово, а вот для тулзов большого проекта может иметь перспективы неприятных поисков багов.
  2. На момент разыменования указателя на владельца, он тупо может быть не валиден.
По хорошему, владелец должен предоставлять объектам владения, некие сущности для обратных запросов, которые будут это все обеспечивать.