OLP. Problemi di applicazione - pagina 5

 

In qualche modo, la questione se il multi-purposing influenzi o meno la velocità di elaborazione del codice della CPU è passata completamente inosservata(2011.04.04 21:58).

Se la domanda sembra scorretta, stupida, ecc. - allora scrivi così.

 
Yedelkin:

In qualche modo, la questione se il multi-purposing influenzi o meno la velocità di elaborazione del codice della CPU è passata completamente inosservata(2011.04.04 21:58).

Se la domanda sembra scorretta, stupida, ecc. - scrivilo così.

La domanda è perfettamente logica, la risposta è no, non lo fa.

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);
  }
//+------------------------------------------------------------------+
 

Ce l'ho! Beh, mi hai dato un sacco di incoraggiamento! Ora raddoppierò il piacere di timbrare i metodi annidati :)

Urain, grazie per l'esempio! Pur non avendo esperienza di programmazione, a volte è difficile indovinare se stessi per controllare e scrivere il codice corretto. E qui tutto è chiaro e comprensibile.

 

Domanda. Un'istanza di una classe figlia può cancellare se stessa? In altre parole, funzionerà un tale costrutto?

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);
  }
Il compilatore non si lamenta di questo costrutto.
 
Yedelkin:

Domanda. Un'istanza di una classe figlia può cancellare se stessa? In altre parole, questa costruzione funzionerà?

Il compilatore non si lamenta di questo costrutto.

Se ho capito bene, non mi piacciono i puntatori (e non li uso spesso, specialmente in MQL5), il bambino dovrebbe essere così

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

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

Pertanto, l'applicazione sarebbe come questa

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

PS

È un bug (o una caratteristica del compilatore) che il compilatore ha mancato?

Naturalmente, possiamo assumere che il discendente abbia passato la classe di cui abbiamo bisogno, ma le strutture e le funzionalità delle due classi potrebbero essere molto diverse. Cosa succede allora?

C_A *pointer=new C_B;
 

E quando si usa il codice iniziale in questo modo, si verifica una perdita di memoria, anche se tutti i controlli del compilatore sono stati superati (e non ha nemmeno menzionato eventuali problemi)

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

Ecco il risultato (capisco che l'oggetto puntatore non viene cancellato correttamente a causa della perdita di memoria):

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:

Se ho capito bene, non mi piacciono i puntatori (e non li uso spesso, specialmente in MQL5), allora il discendente dovrebbe essere così

Guarda. Ho dichiarato il metodo void Del(C_A *p) con il modificatore public nella classe padre. Quindi, la classe figlio ha ereditato completamente questo metodo. Così non ho bisogno di ridichiarare lo stesso metodo nella classe figlio. Per quanto riguarda
C_A *pointer=new C_B;
Ho preso questa idea da Tetris, e funziona bene per me. Naturalmente, non sarebbe giusto usare questa linea in modo assoluto, ma è molto adatta per scopi simili a quelli risolti nel tetris.
 
Yedelkin:

In qualche modo, la questione se il multi-purposing influenzi o meno la velocità di elaborazione del codice del processore(2011.04.04 21:58) è lasciata completamente disattesa.

Se la domanda sembra scorretta, stupida, ecc. - scrivilo e basta.

La risposta alla logica -- più semplici e logiche sono le primitive, più efficiente sarà l'ottimizzatore.

La cosa principale è non esagerare :)

 

Leggermente modificato il codice dello script:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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);
  }

Uscite

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:
Guarda. Ho dichiarato il metodo void Del(C_A *p) con il modificatore public nella classe padre. Quindi la classe figlio ha ereditato completamente questo metodo. Così non ho bisogno di ridichiarare lo stesso metodo nella classe figlio. Per quanto riguarda questa idea, l'ho presa da Tetris e ha funzionato molto bene per me. Naturalmente, non sarebbe corretto usare questa stringa in modo assoluto, ma è molto adatta per scopi simili a quelli risolti nel tetris.

Anche assumendo che void Del(C_A *p) nell'antenato sia sufficiente per cancellare qualsiasi puntatore discendente, non vedo il senso di usare

C_A *pointer=new C_B;

PS

L'unico posto dove posso immaginare la necessità di un tale approccio è la creazione di un array di oggetti vari che sono discendenti della stessa classe (in alternativa, passando un parametro del tipo di classe "base" in una funzione o procedura).