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

 
GreyCardinal:

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

Чтоб Init() правильно отработал, его нужно вызвать после конструирования объекта. 

Или нет?

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

Как-то так.

По крайней мере вот это работает:

void OnStart()
  {
   CO2=new CCO2;
   CO2.Init();
   Print(CO2.Name()," filename=",CO2.filename);
   delete CO2;
   
   H2O=new CH2O;
   H2O.Init();
   Print(H2O.Name()," filename=",H2O.filename);
   delete H2O;
  }

To MetaQuotes :  Если я всё правильно понял, лучше вообще запретить вызов виртуальных функций в конструкторах. Дабы.

Или уж сделать их работоспособными. В чём сомневаюсь.

 

Только-только познакомился с параметрическими конструкторами. Но представляется, что в примере

//+------------------------------------------------------------------+
//| класс для хранения фамилии и имени персонажа                     |
//+------------------------------------------------------------------+
class CPerson
  {
   string            m_first_name;     // имя 
   string            m_second_name;    // фамилия
public:
   //--- пустой конструктор по умолчанию
                     CPerson() {Print(__FUNCTION__);};
   //--- параметрический конструктор
                     CPerson(string full_name);
   //--- конструктор со списком инициализации
                     CPerson(string surname,string name): m_second_name(surname, m_first_name(name)) {};
   void PrintName(){PrintFormat("Name=%s Surname=%s",m_first_name,m_second_name);};
  };
в выделенной строчке неправильно расставлены круглые  скобки.
 
Yedelkin:

Только-только познакомился с параметрическими конструкторами. Но представляется, что в примере

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

Техническое сообщение (начало небольшого обсуждения на тему инициализации, в том числе и в конструкторах). Перенесено, чтобы не затерялось под тяжелой поступью новичков: https://www.mql5.com/ru/forum/58/page31#comment_66890

Изучаем и пишем вместе на MQL5
Изучаем и пишем вместе на MQL5
  • www.mql5.com
2) вывод всей возможной информации по инструментам, ордерам и др.
 

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

Теперь появились списки инициализации, позволяющие инициализировать переменные пользовательскими значениями. Есть ли какая-нибудь разница в скорости инициализации между автоматической инициализацией и инициализацией пользовательским значением? Иными словами, увеличивается ли количество "тактов компьютера" при использовании списков инициализации (и пользовательских значений)  по сравнению с автоматической инициализацией?

 
Yedelkin: Иными словами, увеличивается ли количество "тактов компьютера" при использовании списков инициализации (и пользовательских значений)  по сравнению с автоматической инициализацией?
А что, если несколько тактов сэкономим, это даст существенный выигрыш ? Тем более, что инициализация проводится однократно, а значения всё равно придётся присваивать впоследствии.
 
Valmars:
А что, если несколько тактов сэкономим, это даст существенный выигрыш ? Тем более, что инициализация проводится однократно, а значения всё равно придётся присваивать впоследствии.
Ответ не по существу. Лично для меня вопрос важный, поскольку хочу разобраться  в технике. Каждый отдельный такт важен. Иначе бы не было самого вопроса. Клепать чайники без оглядки на правила - умеем.
 
Yedelkin:
Лично для меня вопрос важный, поскольку хочу разобраться  в технике.

Правильный подход, все бы так. Списки инициализации это следствие введения параметрических конструкторов.

Разберем два примера:

class A
{
private:
   // конструктор по умолчанию недоступен
   A(){}
public:
   A(const double& value)
      : m_Value(value)
   {}
private:
   double m_Value;
}

class B
{
public:
   B()
   // т.к. коструктор А не имеет конструктора по умолчанию, единственный способ
   // использования класса -- инициализация в списке инициализации.
   // по-другому просто не должно скомпилиться
      : A(0)
   {
   }

private:
   A m_Value;
}

Тут все в комментах написано.

Пример 2:

class A
{
public:
   A()
   {
      Init(0);
   }
   
   A(const double& value)
   {
      Init(value);
   }
   
   void Init(double value)
   {
      // очень тяжелая функция
   }
};

class B
{
public:
   // вариант1, правильный
   B(const double& value)
      : m_Value(value)
   {
   }

/*
   // вариант2, неправильный
   B(const double& value)
   {
      m_Value.Init(value);
   }
*/

private:
   A m_Value;
};
Итак в варианте 1 имеем 1 вызов Init, в варианте 2 -- 2 вызова. А т.к. функция "типа" очень тяжелая, плюс налицо.
 

TheXpert, спасибо огромное! Буду разбираться.

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

 
Yedelkin:

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

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