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

 

Как-то совсем без внимания остался вопрос о том, не сказывается ли многообёрточность на скорости обработки кода процессором (2011.04.04 21:58)

Если вопрос выглядит некорректным, глупым и т.д. - так и напишите. 

 
Yedelkin:

Как-то совсем без внимания остался вопрос о том, не сказывается ли многообёрточность на скорости обработки кода процессором (2011.04.04 21:58)

Если вопрос выглядит некорректным, глупым и т.д. - так и напишите. 

Вопрос вполне логичный, ответ нет, не сказывается.

2011.04.09 10:21:31     Черновик 31 (GBPUSD,H1) время c обёртками=1656
2011.04.09 10:21:29     Черновик 31 (GBPUSD,H1) время без обёртки=1766


class CA
  {
private:
   uint              func1(int count){return(func2(count));};
   uint              func2(int count){return(func3(count));};
   uint              func3(int count){return(func4(count));};
   uint              func4(int count){return(func5(count));};
   uint              func5(int count){return(func6(count));};
   uint              func6(int count){return(func7(count));};
   uint              func7(int count){return(func8(count));};
   uint              func8(int count){return(func9(count));};
   uint              func9(int count)
     {
      uint start=GetTickCount();
      double a=123456.4567879;double b=234.568;double temp;
      for(int i=0;i<count;i++)
        {
         if(i%2==0)temp=a/b;
         else temp=a*b;
        }
      return(GetTickCount()-start);
     };
public:
                     CA(void){};
                    ~CA(void){};
   uint              func(int count){return(func1(count));};

  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
          Print("время без обёртки=",  func(100000000));
   CA a; Print("время c обёртками=",a.func(100000000));
  }
//+------------------------------------------------------------------+
uint func(int count)
  {
   uint start=GetTickCount();
   double a=123456.4567879;double b=234.568;double temp;
   for(int i=0;i<count;i++)
     {
      if(i%2==0)temp=a/b;
      else temp=a*b;
     }
   return(GetTickCount()-start);
  }
//+------------------------------------------------------------------+
 

Понял! Ну вы меня окрылили! Буду теперь с удвоенным удовольствием штамповать вложенные методы :)  

Urain, спасибо за пример! Пока не имеешь опыта программирования, порой трудно догадаться самому провести проверку и написать правильный код для этого. А тут всё наглядно и понятно.

 

Вопрос. Может ли экземпляр класса-потомка удалить сам себя? Иными словами, будет ли работать такая конструкция:

class C_A
  {
public:
                     C_A(){};
                    ~C_A(){};
   void Del(C_A *p)
     {
      if(CheckPointer(p)==POINTER_DYNAMIC)
        {
         delete p;
        }
     }
  };
class C_B : public C_A
  {
public:
                     C_B(){};
                    ~C_B(){};
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   C_A *pointer=new C_B;
   pointer.Del(pointer);
  }
Компилятор на эту конструкцию не ругается. 
 
Yedelkin:

Вопрос. Может ли экземпляр класса-потомка удалить сам себя? Иными словами, будет ли работать такая конструкция:

Компилятор на эту конструкцию не ругается. 

Если я правильно все понимаю, не люблю я указатели (и не часто их юзаю, особо в MQL5) то потомок так должен выглядеть

class C_B : public C_A
{
public:
                     C_B(){};
                    ~C_B(){};

   void Del(C_B *p)
     {
      if(CheckPointer(p)==POINTER_DYNAMIC)
        {
         delete p;
        }
     }
};

Следовательно применение по идеи будет таким

void OnStart()
{
C_B *pointer=new C_B;
pointer.Del(pointer);
}

PS

А не баг ли (или не учтенная особенность компилятора) что компилятор пропустил такое?

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

C_A *pointer=new C_B;
 

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

void OnStart()
{
C_B *pointer=new C_B;
pointer.Del(pointer);
}

Результат вот (как я понимаю из-за протечки памяти объект указатель корректно не удален):

2011.04.09 19:21:07    Forum (EURUSD,D1)    16 bytes of leaked memory
2011.04.09 19:21:07    Forum (EURUSD,D1)    1 object of type C_B left
2011.04.09 19:21:07    Forum (EURUSD,D1)    1 undeleted objects left
 
Interesting:

Если я правильно все понимаю, не люблю я указатели (и не часто их юзаю, особо в MQL5) то потомок так должен выглядеть

Ну смотрите. Я объявил метод void Del(C_A *p) с модификатором public в родительском классе. Значит, класс-потомок полностью унаследовал этот метод. Поэтому мне не требуется повторно в классе-потомке объявлять этот же метод. Что касается
C_A *pointer=new C_B;
то эту идею я подсмотрел из тетриса, и мне она очень оказалась кстати. Разумеется, напропалую использовать эту строчку было бы неправильно, но в целях, схожих с решенными в тетрисе, очень подходит.
 
Yedelkin:

Как-то совсем без внимания остался вопрос о том, не сказывается ли многообёрточность на скорости обработки кода процессором (2011.04.04 21:58)

Если вопрос выглядит некорректным, глупым и т.д. - так и напишите. 

Ответ по логике -- чем проще и логичнее примитивы, тем эффективнее будет работать оптимизатор.

Главное с этим делом не переборщить :)

 

Чуть модифицировал код скрипта:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_A
  {
public:
                     C_A(){ Print("Запущен класс С_А"); };
                    ~C_A(){Print("Закрыт класс С_А");};
   void Del(C_A *p)
     {
      if(CheckPointer(p)==POINTER_DYNAMIC)
        {
         delete p;
         Print("Удалён объект p");
        }
     }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B : public C_A
  {
public:
                     C_B(){ Print("Запущен класс С_В"); };
                    ~C_B(){Print("Закрыт класс С_В");};
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   C_A *pointer=new C_B;
   if(pointer!=NULL) Print("указатель pointer проинициализирован");
   pointer.Del(pointer);
  }

Выдаёт

EL      0       ttttttttttttt (EURUSD,M1)       15:08:27        Запущен класс С_А
MS      0       ttttttttttttt (EURUSD,M1)       15:08:27        Запущен класс С_В
DJ      0       ttttttttttttt (EURUSD,M1)       15:08:27        указатель pointer проинициализирован
IH      0       ttttttttttttt (EURUSD,M1)       15:08:27        Закрыт класс С_В
CG      0       ttttttttttttt (EURUSD,M1)       15:08:27        Закрыт класс С_А
RO      0       ttttttttttttt (EURUSD,M1)       15:08:27        Удалён объект p
 
Yedelkin:
Ну смотрите. Я объявил метод void Del(C_A *p) с модификатором public в родительском классе. Значит, класс-потомок полностью унаследовал этот метод. Поэтому мне не требуется повторно в классе-потомке объявлять этот же метод. Что касается то эту идею я подсмотрел из тетриса, и мне она очень оказалась кстати. Разумеется, напропалую использовать эту строчку было бы неправильно, но в целях, схожих с решенными в тетрисе, очень подходит.

Даже если предположить что void Del(C_A *p) в предке будет достаточно для удаления указателя любого потомка то не вижу смысла использовать

C_A *pointer=new C_B;

PS

Единственное где я могу представить необходимость в таком подходе - Создание массива из разношёрстных объектов которые являются потомками одного класса (как вариант передача в функцию или процедуру параметра с типом "базового" класса).

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