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

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

 

//1-ый вариант. Переменная-член strA инициализируется автоматически
class A
  {
public:
   string            strA;
                     A(void) { Print("strA=",strA); };
                    ~A(void){};
  };
//2-ой вариант. Переменная-член strB инициализируется при помощи инициализатора пользовательским значением
class B
  {
public:
   string            strB;
                     B(const string str) : strB(str) { Print("strB=",strB); }
                    ~B(void){};
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   A a1;
   B b1("Пользовательское значение");
  }

 Пример простой. Допустим, что на автоматическую инициализицию члена a1.strA тратится 15 "тактов компьютера". Пришёл к предварительному выводу, что и на инициализацию члена b1.strB тратится также 15 тактов. Это правильно?

 

В классе CExpert стандартной библиотеки существуют такие вот защищенные декларации

//--- trading objects
CExpertTrade     *m_trade;    // trading object
CExpertSignal    *m_signal;   // trading signals object
CExpertMoney     *m_money;    // money manager object
CExpertTrailing  *m_trailing; // trailing stops object

В тоже время конструктор этого объекта содержит следующие строки

m_trade    =NULL;
m_signal   =NULL;
m_money    =NULL;
m_trailing =NULL;

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

Компилятор скомпилировал все без предупреждений и ошибок, но при установке советника на чарт вылезла критическая ошибка 281 (Invalid pointer access) и советник был удален с чарта.

В связи с этим возникли вопросы такого плана:

1. Как правильно поступить в конструкторе (указав NULL или сразу прописав указатель на конкретный объект)?

2. Нужна ли обязательная последующая инициализация указателей по типу InitTrade?

 
Interesting:

В классе CExpert стандартной библиотеки существуют такие вот защищенные декларации

В тоже время конструктор этого объекта содержит следующие строки

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

Компилятор скомпилировал все без предупреждений и ошибок, но при установке советника на чарт вылезла критическая ошибка 281 (Invalid pointer access) и советник был удален с чарта.

В связи с этим возникли вопросы такого плана:

1. Как правильно поступить в конструкторе (указав NULL или сразу прописав указатель на конкретный объект)?

2. Нужна ли обязательная последующая инициализация указателей по типу InitTrade?

1. Правильно и так и так. Всё зависит от конкретной реализации класса (не конкретно CExpert). Однако, динамические объекты лучше создавать в методе InitXXX, возвращающем bool (ведь конструктор не возвращает результата исполнения и придётся взводить/сбрасывать флаг инициализации с последующим его (флага) анализом).

2. Конечно нужна. Иначе критическая ошибка 281 (Invalid pointer access).

PS. Кстати, спасибо. Нужно будет мне вставить проверки указателей перед использованием.

 
Yedelkin:

 Пример простой. Допустим, что на автоматическую инициализицию члена a1.strA тратится 15 "тактов компьютера". Пришёл к предварительному выводу, что и на инициализацию члена b1.strB тратится также 15 тактов. Это правильно?

Нет, дело вообще не в тактах. Ну или не совсем в тактах.
 
TheXpert:
Нет, дело вообще не в тактах. Ну или не совсем в тактах.

ОК, тогда уж совсем простой вопрос: что быстрее инициализируется по времени, член a1.strA или член b1.strB из приведённого выше примера?

Или что почитать "точечно"? Физически нет возможности  изучать программинг на "машинно-процессорном" уровне.

 
Yedelkin:

ОК, тогда уж совсем простой вопрос: что быстрее инициализируется по времени, член a1.strA или член b1.strB из приведённого выше примера?

Или что почитать "точечно"? Физически нет возможности  изучать программинг на "машинно-процессорном" уровне.

a1.strA проинициализируется быстрее, так как процесс её инициализации заключается в простом обнулении по месту. Для b1.strB будет произведено распределение памяти.

Однако эту разницу измерить довольно сложно, так как она гораздо меньше одного процента с учётом кода, который вокруг инициализации

 
Yedelkin:

что быстрее инициализируется

вопрос некорректен.
 
stringo:

 Для b1.strB будет произведено распределение памяти.

Вот, спасибо - недостающее звено в моей логике.

 TheXpert, спасибо за помощь. Пытался объяснить своими словами суть вопроса. Согласен, что по-настоящему корректный вопрос задается теми, кто в теме. Но они обычно вопросы моего уровня и не задают :)

 
uncleVic:

1. Правильно и так и так. Всё зависит от конкретной реализации класса (не конкретно CExpert). Однако, динамические объекты лучше создавать в методе InitXXX, возвращающем bool (ведь конструктор не возвращает результата исполнения и придётся взводить/сбрасывать флаг инициализации с последующим его (флага) анализом).

2. Конечно нужна. Иначе критическая ошибка 281 (Invalid pointer access).

PS. Кстати, спасибо. Нужно будет мне вставить проверки указателей перед использованием.

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

Уточню вопрос - Как быть если 281 ошибка возникает после выполнения всех этапов инициализации, но на основную работу эксперта это не повлияет настолько критически чтобы его совсем не запускать?

 
Interesting:

Допустим если возникает ошибка 281, но при этом желательно чтобы советник не выгружался. Как быть тогда?

Уточню вопрос - Как быть если 281 ошибка возникает после выполнения всех этапов инициализации, но на основную работу эксперта это не повлияет настолько критически чтобы его совсем не запускать?

 

"Invalid pointer access" == "Попытка к обращения к некорректному указателю"? Если да, то

Попытка к обращения к некорректному указателю приводит к критическому завершению программы. Поэтому существует необходимость использования функции CheckPointer() перед использованием указателя. Указатель может быть некорректным в следующих случаях:

  • указатель равен NULL;
  • если объект был уничтожен при помощи оператора delete.
Причина обращения: