OLP. Problèmes d'application - page 5

 

D'une manière ou d'une autre, la question de savoir si la polyvalence affecte ou non la vitesse de traitement du code du CPU est passée complètement inaperçue(2011.04.04 21:58).

Si la question semble incorrecte, stupide, etc. - alors écrivez-le.

 
Yedelkin:

D'une manière ou d'une autre, la question de savoir si la polyvalence affecte ou non la vitesse de traitement du code du CPU est passée complètement inaperçue(2011.04.04 21:58).

Si la question semble incorrecte, stupide, etc. - il suffit de l'écrire ainsi.

La question est parfaitement logique, la réponse est non, elle ne l'est pas.

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

Je l'ai eu ! Eh bien, vous m'avez donné beaucoup d'encouragement ! Je vais doubler le plaisir de tamponner des méthodes imbriquées maintenant :)

Urain, merci pour l'exemple ! Bien que vous n'ayez aucune expérience de la programmation, il est parfois difficile de se deviner pour vérifier et écrire un code correct. Et ici, tout est clair et compréhensible.

 

Question. Une instance d'une classe enfant peut-elle se supprimer elle-même ? En d'autres termes, une telle construction fonctionnera-t-elle ?

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);
  }
Le compilateur ne se plaint pas de cette construction.
 
Yedelkin:

Question. Une instance d'une classe enfant peut-elle se supprimer elle-même ? En d'autres termes, cette construction fonctionnera-t-elle ?

Le compilateur ne se plaint pas de cette construction.

Si je comprends bien, je n'aime pas les pointeurs (et je ne les utilise pas souvent, surtout en MQL5), l'enfant devrait ressembler à ceci

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

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

Par conséquent, l'application ressemblerait à ceci

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

PS

Est-ce un bogue (ou une caractéristique du compilateur) que le compilateur l'ait manqué ?

Bien sûr, nous pouvons supposer que le descendant a transmis la classe dont nous avons besoin, mais les structures et les fonctionnalités des deux classes peuvent être très différentes. Que se passe-t-il alors ?

C_A *pointer=new C_B;
 

Et en utilisant le code initial comme ceci, une fuite de mémoire se produit du tout, bien que tous les contrôles du compilateur aient été passés (et il n'a même pas mentionné de problèmes possibles).

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

Voici le résultat (je comprends que l'objet pointeur n'est pas correctement supprimé à cause de la fuite de mémoire) :

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:

Si je comprends bien, je n'aime pas les pointeurs (et je ne les utilise pas souvent, surtout dans MQL5), alors le descendant devrait ressembler à ceci

Regardez. J'ai déclaré la méthode void Del(C_A *p) avec le modificateur public dans la classe parent. Ainsi, la classe enfant a entièrement hérité de cette méthode. Je n'ai donc pas besoin de redéclarer la même méthode dans la classe enfant. Quant à
C_A *pointer=new C_B;
J'ai eu cette idée à partir de Tétris, et ça marche très bien pour moi. Bien sûr, il ne serait pas bon d'utiliser cette ligne à tout prix, mais elle convient très bien à des fins similaires à celles résolues dans le tetris.
 
Yedelkin:

D'une manière ou d'une autre, la question de savoir si la polyvalence affecte ou non la vitesse de traitement du code du processeur(2011.04.04 21:58) n'est pas du tout abordée.

Si la question semble incorrecte, stupide, etc. - Il suffit de l'écrire.

La réponse est logique : plus les primitives sont simples et logiques, plus l'optimiseur sera efficace.

L'essentiel est de ne pas en faire trop :)

 

Légèrement modifié le code du 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);
  }

Sorties

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:
Regardez. J'ai déclaré la méthode void Del(C_A *p) avec le modificateur public dans la classe parent. La classe enfant a donc entièrement hérité de cette méthode. Je n'ai donc pas besoin de redéclarer la même méthode dans la classe enfant. Quant à l'idée, je l'ai trouvée dans Tétris, et elle m'a été utile. Bien sûr, il ne serait pas correct d'utiliser carrément cette chaîne, mais elle convient très bien à des fins similaires à celles résolues dans le tetris.

Même en supposant que void Del(C_A *p) dans l'ancêtre est suffisant pour supprimer tout pointeur descendant, je ne vois pas l'intérêt d'utiliser

C_A *pointer=new C_B;

PS

Le seul endroit où je peux imaginer le besoin d'une telle approche est la création d'un tableau d'objets divers qui sont des descendants de la même classe (ou encore le passage d'un paramètre du type de la classe "de base" dans une fonction ou une procédure).

Raison: