ООП. Вопросы применения - страница 11

 
Interesting:

Как хорошо уметь читать... :)

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

А вот как интересно быть если параметров много и все их не запихать в базовый класс?

Насколько я понимаю дополнительно ввести индекс параметра который передаем (также в классе можно создать массив с параметрами уложенными в него по индексу)?

Я то же не понял...

В моём примере есть индекс, только он не числовой в явном виде, а перечисление....

 

Забудьте, оно того не стоит.

 

Interesting:

Yedelkin:

В общем, по итогам обсуждения проблемы https://www.mql5.com/ru/forum/3566/page6#comment_58280 отправил заявку в СД. 

1. Не знаю, не знаю.

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

Отчитываюсь.

Заявка была такая:
...

Предлагаю:

1. Уточнить раздел Справочника "Полиморфизм" в части указания того, как правильно заполнять массив  shapes[10] экземплярами классов, производных от CShape (привести пример).

2. Проверить правильность написания строчки:

CShape[10] shapes;                       // массив объектов CShape

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

class CShape{};

class CCircle{} : public CShape

class CSquare{} : public CShape

 Ответ:

Rashid Umarov 2011.04.11 15:17

 

На момент написания справки некоторые моменты еще не были ясны для документирования. Мы исправим этот момент и добавим правильный код. Спасибо за Ваше сообщение.

В справку будет добавлено расширенное описание, вот отрывок из него:

Предполагается, что в программе у нас используются объекты разного типа (CCircle и CSquare), но унаследованные от одного базового типа CShape. Полиморфизм позволяет нам создать массив объектов базового типа CShape, но при объявлении этого массива сами объекты еще неизвестны и их тип неопределен.

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

Для динамического создания объектов используется оператор new, каждый такой объект нужно самостоятельно и явно удалять оператором delete. Поэтому мы объявим массив указателей типа CShape и для каждого его элемента создадим объект нужного типа (new Имя_класса), как это показано в примере скрипта:

//+------------------------------------------------------------------+

//| Script program start function                                    |

//+------------------------------------------------------------------+

void OnStart()

  {

//--- объявим массив указателей объектов базового типа 

   CShape *shapes[5];   // массив указателей на объекты CShape



//--- здесь заполняем массив производными объектами

//--- объявим указатель на объект типа CCircle

   CCircle *circle=new CCircle();

//--- задаем свойства объекта по указателю circle

   circle.SetRadius(2.5);

//--- поместим в shapes[0] значение указателя

   shapes[0]=circle;



//--- создаем еще один объект CCircle и запишем его указатель в shapes[1]

   circle=new CCircle();

   shapes[1]=circle;

   circle.SetRadius(5);



//--- тут мы намеренно "забыли" задать значение для shapes[2]

//circle=new CCircle();

//circle.SetRadius(10);

//shapes[2]=circle;



//--- для неиспользуемого элемента установим значение NULL

   shapes[2]=NULL;



//--- создаем объект CSquare и запишем его указатель в shapes[3]

   CSquare *square=new CSquare();

   square.SetSide(5);

   shapes[3]=square;



//--- создаем объект CSquare и запишем его указатель в shapes[4]

   square=new CSquare();

   square.SetSide(10);

   shapes[4]=square;



//--- массив указателей есть, получим его размер

   int total=ArraySize(shapes);

//--- пройдем в цикле по всем указателям в массиве 

   for(int i=0; i<5;i++)

     {

      //--- если по указанному индексу указатель является валидным

      if(CheckPointer(shapes[i])!=POINTER_INVALID)

        {

         //--- выведем в лог тип и площадь фигуры

         PrintFormat("Объект типа %d имеет площадь %G",

               shapes[i].GetType(),

               shapes[i].GetArea());

        }

      //--- если указатель имеет тип POINTER_INVALID

      else

        {

         //--- сообщим об ошибке

         PrintFormat("Объект shapes[%d] не инициализирован! Его указатель %s",

                     i,EnumToString(CheckPointer(shapes[i])));

        }

     }



//--- мы должны самостоятельно уничтожить все созданные динамические объекты

   for(int i=0;i<total;i++)

     {

      //--- удалять можно только объекты, чей указатель имеет тип POINTER_DYNAMIC

      if(CheckPointer(shapes[i])==POINTER_DYNAMIC)

        {

         //--- сообщим об удалении

         PrintFormat("Удаляем shapes[%d]",i);

         //--- уничтожим объект по его указателю

         delete shapes[i];

        }

     }

  }


Обратите внимание, что при уничтожении объекта оператором delete необходимо проверить тип его указателя. Удалять с помощью delete можно только объекты, имеющие указатель POINTER_DYNAMIC, для указателей другого типа будет получена ошибка.

Думаю, данный пример полностью раскрывает идею создания массива указателей.
Rashid Umarov 2011.04.11 10:31

Спасибо за сообщение, исправили №2 и №3. Будет в новых версиях справки



 

Вопрос. В стандартной библиотеке используются вот такие строчки

void CTrade::Request(MqlTradeRequest& request) const
  {...}

В Справочнике сказано: "Спецификатор const неприменим к членам структур и классов". Что означает вышеуказанное использование const в методе класса и каковы правила его использования в подобных случаях?

Документация по MQL5: Стандартная библиотека
Документация по MQL5: Стандартная библиотека
  • www.mql5.com
Стандартная библиотека - Документация по MQL5
 

Yedelkin:

...............

Что означает вышеуказанное использование const в методе класса и каковы правила его использования в подобных случаях?

О да, мне тоже давно интересно. Хочется осмысленно пользоваться языком, полностью осознавая "правила игры".
 
Yedelkin:

Вопрос. В стандартной библиотеке используются вот такие строчки

В Справочнике сказано: "Спецификатор const неприменим к членам структур и классов". Что означает вышеуказанное использование const в методе класса и каковы правила его использования в подобных случаях?

Член структуры/класса - это одно, а метод - это другое.

Метод, описанный как const означает, что он не меняет состояние/члены своего класса. То есть, после вызова такого метода внутреннее состояние класса остается неизменным. Используется для дополнительного указания компилятору, чтобы тот проверял попытки изменить члены класса.

 
Renat:

Член структуры/класса - это одно, а метод - это другое.

Метод, описанный как const означает, что он не меняет состояние/члены своего класса. То есть, после вызова такого метода внутреннее состояние класса остается неизменным. Используется для дополнительного указания компилятору, чтобы тот проверял попытки изменить члены класса.

Ух ты. Спасибо! А я голову ломал.

 
TheXpert:
Кстати, логичный вопрос, раз уж разговор зашел -- инструкции volatile нет и не предвидится?

А как её можно применить? , ведь потоки между собой не взаимодействуют,

вот если бы данные можно было свободно передавать между потоками тогда да, была бы необходимость в такой инструкции.

 
Чорд, писал и думал, что пишу что-то не то :) теперь понял что. Конечно же не volatile -- mutable :))
 
class COracleTemplate
  {
private:
public:
   string            filename;
                     COracleTemplate(){Init();};
                    ~COracleTemplate(){DeInit();};
   virtual void      Init(){filename=this.Name();Print("loadSettings from ",filename);};
   virtual void      DeInit(){Print("saveSettings to ",filename);};
   virtual string    Name(){return("Prpototype");};
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CCO2:public COracleTemplate
  {
   virtual string    Name(){return("CO2");};
  };
class CH2O:public COracleTemplate
  {
   virtual string    Name(){return("H2O");};
  };
COracleTemplate* CO2,*H2O;
void OnStart()
  {
   CO2=new CCO2;
   Print(CO2.Name()," filename=",CO2.filename);
   delete CO2;
   
   H2O=new CH2O;
   Print(H2O.Name()," filename=",H2O.filename);
   delete H2O;
   
  }

Добрый день.

Такой вопрос

по коду выше

что я сделал не так или это в принципе недостижимо в МТ5?

Хочется (как  я думаю очевидно) - получать в переменных filename переопределенные имена...

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