Давайте вместе разберем CObject ? - страница 2

 
Vladimir Pastushak:

Может кто то простым языком и примером показать зачем этот CObject  и как он работает ?

не надо трогать каку.

Если вкратце, с помощью этого костыля решались проблемы при реализации стандартной библиотеки.

 

Как для меня, это простой пример навигации с использованием указателей.
Кто помнит PL/1, введение в С++ или WIN API - используют. 
)

 

Когда-то давно, когда в MQL ещё не было шаблонов классов, придумали класс CObject.

Единственное для чего он нужен, это для того чтобы складывать разные классы в контейнеры из стандартной библиотеки.

Для этого их нужно наследовать от CObject.

Но сейчас, разработчикам следовало бы написать нормальные контейнеры на шаблонах.

 
Vladimir Pastushak:

почему две и как их потом листать ?


Еще есть класс CList - класс для создания связанного списка, в нем используется эти Prev и Next (для него и сделаны) - указывают на следующий и предыдущий элементы списка. В отличие от массива удаление и добавление элементов в список очень не затратно, не нужно смещать весь массив, достаточно изменить Prev и Next у двух соседних элементов и у добавляемого элемента их указать. 

 
Vladimir Pastushak:

Разбираюсь детально с ООП и никак не могу вьехать в этот код

Прочитал несколько статей в том чиле и эту https://www.mql5.com/ru/articles/179

и ника не могу понять, что делает этот код ?  

Может кто то простым языком и примером показать зачем этот CObject  и как он работает ?


Абстрактный класс, часто надо от него наследоваться.

 

Считаю класс CObject - очень даже правильным и нужным классом.

Никакой это не "костыль" и вовсе не замена шаблона.

У меня ВСЕ классы во всех проектах - наследуются от Объекта СMyObject: public CObject  - то есть, от моего наследника класса CObject

В классе CObject инкапсулированы возможности списка и сортированного массива. По сути, CObject - это "объект списка или массива".

На мой взгляд - очень нужные функции.

   CObject          *m_prev;
   CObject          *m_next;

Вот - это как раз указатели, которые используются классом CList - объекты "цепляются" один за другой, что позволяет очень просто организовать списки любых объектов, проснаследованных от CObject.

Соответственно, в классе есть public-методы получения предыдущего и следующего объекта в списке.

Также есть функция сравнения, которая позволяет сортировать любые объекты, пронаследованные от данного по любым критериям.

Есть функции сериализации объекта в файл (очень странно, что в качестве параметра этой функции передается хэндл файла, а не указатель на объект CFile )

Наконец, есть функция, которая возвращает тип объекта.

Понятное дело, что все функции виртуальны - то есть, при проектировании своего объекта - необходимо их имплементировать.

В своем классе CMyObject я также добавил функции опознания класса-наследника (для того, чтобы при преобразовании указателей можно было контролировать валидность объекта), и пользовательского значения (чтобы можно было его устанавливать при создании объекта, и отличать объекты один от другого).

Неоднократно в своей практике сталкивался с тем, что класс, изначально не наследовался от CObject, поскольку не расчитывалось, что объекты данного класса будут в массивах и списках, но в последствии - такая необходимость возникала.

 

Сколько участников столько и мнений, есть у кого то простые примеры ?

 
Vladimir Pastushak:

Сколько участников столько и мнений, есть у кого то простые примеры ?

Какие примеры нужны-то ? Прямо свой код предложить не могу - слишком в нем много связей... Что-то простейшее, навскидку... Ну сейчас попробую набросать...

Скажем, у меня есть класс СMT4PositionInfo - позиция в МТ4, которая представляет из себя CArrayObj объектов-открытых ордеров. Каждый ордер - это объект COrderInfo, в который при инициализации записываются все данные каждого ордера.

Объект COrderInfo пронаследован от CObject. Соответственно, добавление ордеров выглядит следующим образом (упрощенно, много проверок пропущено):

CArrayObj aoPositionInfo; // Объявляем массив ордеров
.... // Здесь выбираем позицию, чтобы можно было выбрать все ордера
// В цикле добавляем выбранные ордера в объект позиции
COrderInfo * poiOrderInfo = new COrderInfo;
poiOrderInfo.GetInfoFromTerminal();
aoPositionInfo.Add(poiOrderInfo)
... // Цикл закончен
// В этой точке - все ордера собраны в массив. 
// Теперь можно сортировать этот массив по любому признаку, например по времени.
aoPositionInfo.Sort(BY_TIME);

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

COrderInfo::Compare(const CObject *node,const int mode)
{
COrderInfo* pOrder = node; // Преобразуем переданный указатель на объект к нашему ордеру, здесь я также всегда ставлю проверку на валидность (пропущена)
switch(mode)  // В зависимости от типа сортировки - возвращаем ту или иную функцию сравнения
{
case BY_TIME: return (_CompareByTimeWith(pOrder));
case BY_VOLUME: return (_CompareByVolumeWith(pOrder));
case BY_TP: return (_CompareByTPWith(pOrder));
case BY_SL: return (_CompareBySLWith(pOrder));
}
};

Все !

Сама функция быстрой сортировки - определяется в классе CArray, предка ArrayObj.

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

Для создания списка же объектов на основе CList - вобще ничего не надо, просто пронаследоваться от CObject - и цепляй в лист объекты, как тебе хочется, удаляй их, запрашивай.

 

Если Правильно вставляем код на форуме, то и код сразу становится прекрасно оформлен!

 

Как сделать что бы t видел только func_2 и func_4 ?

class test
  {
public:
   virtual int       func_1(); 
   virtual int       func_2();
   virtual int       func_3();
   virtual int       func_4();
   public:
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class test2 : protected test  // override
  {
public:
  };

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