Erreurs, bugs, questions - page 2363

 
Igor Makanu:

typedef est un sujet, j'ai essayé, mais ça ne s'est pas bien passé, je dois encore trouver où je me suis trompé, mon exemple devrait fonctionner avec typedef aussi !

Mais vous pouvez le rendre plus simple et plus élégant - sans parenthèses ni pointeurs inutiles - (et il se compile sans erreurs étranges)))).

#property strict

class CObject{ };
class CMyclass: public CObject {
  public: CMyclass *operator[] (CObject*p){ CMyclass*r = dynamic_cast<CMyclass*>(p); 
                                return CheckPointer(r)!=POINTER_INVALID?r:NULL; }
          int f(){ return 1; } 
} my ;

void OnStart()
{
  CObject*co=new CMyclass;
  
  my[co].f();
}
 
Ilya Malev:

Pouvez-vous le rendre plus simple et plus élégant - sans parenthèses et pointeurs inutiles - (et il compile sans erreurs étranges)))).

votre exemple ne fonctionnera pas dans mon cas, mes objets sont créés dynamiquement, je ne leur attribue même pas de nom, alors que votre exemple utilise un nom de pointeur, j'ai essayé de cette façon, le compilateur ne laisse pas passer : '[' - nom attendu tst_cast.mq4 32 15


#property strict
#include <Object.mqh>
#include <Arrays\List.mqh>
//+------------------------------------------------------------------+
class CMyclass:public CObject
  {
public:
   int               x;
   double            y;
   CObject           *obj;
   void              CMyclass(void):x(-1),y(-2.2)  {                       }
   public: CMyclass *operator[] (CObject*p){ CMyclass*r = dynamic_cast<CMyclass*>(p); 
                                             return CheckPointer(r)!=POINTER_INVALID?r:NULL; }         
  };
//+------------------------------------------------------------------+
void OnStart()
  {
   CList *base=new CList;
   for(int i=0;i<3;i++)
     {
      base.Add(new CMyclass);
      ((CMyclass*)base.GetCurrentNode()).x = 99;
      ((CMyclass*)base.GetCurrentNode()).y = 555;
      CMyclass[base.GetCurrentNode()].x = 111;
     }

   for(int i=0;i<3;i++)
     {
      Print(((CMyclass*)base.GetNodeAtIndex(i)).x," : ",((CMyclass*)base.GetNodeAtIndex(i)).y);
     }
   delete base;
  }
//+------------------------------------------------------------------+

SZZ : J'ai commencé à comprendre un peu ce que vous suggérez, mais toujours pas de résultat, je peux faire sans dynamic_cast <>, ajouter * le champCObject, en théorie ça devrait être comme ça :

...
 CObject           *obj;
 CMyclass          *operator[](CObject*p)        { obj = p; return(obj); }          
  };

Je pense que cela fonctionnera un peu plus vite que votre exemple avec dynamic_cast <> - le sens est le même

 
Igor Makanu:

s'il est possible de déréférencer un pointeur *CObject dans MQL ?

J'ai essayé différentes variantes, voici un script de test, j'ajoute 3 éléments Myclass à la liste liée et ensuite je change les valeurs des champs CMyclass, ça marche :

Puis-je modifier les champs des éléments CMyclass créés dynamiquement, sans pointeur intermédiaireCMyclass *result ?

Comme ceci :(CMyclass *)(base.GetCurrentNode()).x = 99 ;

PS : Je pense que vous devez utiliser typedef , mais jusqu'à présent sans succès.

Ce que vous avez écrit est juste une utilisation implicite de la même chose :

result=base.GetCurrentNode();

C'est à dire un tel pointeur anonyme, mais fondamentalement juste du sucre syntaxique. Il n'y a presque pas de sucre dans MQL, donc ça ne peut pas être fait de cette façon. Mais je dois noter que le casting en descendant se fait sans aucune vérification ni conversion, donc on ne voit pas bien pourquoi vous n'aimez pas travailler explicitement avec un pointeur.

 
Igor Makanu:

ZS : un peu commencé à comprendre ce que vous suggérez, mais toujours pas de résultat, vous pouvez faire sans dynamic_cast <>, ajouter un champ * CObject , en théorie, il devrait être comme ceci :

Je pense que cela fonctionnera un peu plus vite que votre exemple avec dynamic_cast <> - la signification est la même

Vous pouvez le faire sans champ séparé, comme suggéré ci-dessus, mais uniquement en intégrant l'opérateur.

Il y a une petite différence. Si soudainement un objet non converti en myclass apparaît, alors sans dynamic_cast il y aura une erreur d'exécution, et avec cela, vous obtiendrez NULL en retour. Si vous l'adressez avec .x immédiatement, cela provoquera une erreur d'exécution de toute façon, donc vous n'avez pas besoin de vous en inquiéter =))).

Si nous faisons ce que le docteur a ordonné, nous devrions retourner quelque chose comme une instance de classe spéciale créée pour la gestion des erreurs )))).

P.S. J'ai récemment vérifié la vitesse de dynamic_casta, par rapport au casting habituel - elle était presque la même en cas d'égalité de la classe avec celle attendue.

P.S.S. Quoi qu'il en soit, les for ont l'air plutôt triste ici - lorsque vous travaillez avec des listes, vous devriez utiliser des boucles comme for each (comme ma boucle)
 
Igor Makanu:

ne passe pas le compilateur : '[' - nom attendu tst_cast.mq4 32 15

#property strict
#include <Object.mqh>
#include <Arrays\List.mqh>
//+------------------------------------------------------------------+
class CMyclass:public CObject
  {
public:
   int               x;
   double            y;
   CObject           *obj;
   void              CMyclass(void):x(-1),y(-2.2)  {                       }
   public: CMyclass *operator[] (CObject*p){ CMyclass*r = dynamic_cast<CMyclass*>(p); 
                                             return CheckPointer(r)!=POINTER_INVALID?r:NULL; }         
  };
//+------------------------------------------------------------------+
void OnStart()
  {
   CList *base=new CList;
   for(int i=0;i<3;i++)
     {
      base.Add(new CMyclass);
      ((CMyclass*)base.GetCurrentNode()).x = 99;
      ((CMyclass*)base.GetCurrentNode()).y = 555;
      CMyclass[base.GetCurrentNode()].x = 111;
     }

   for(int i=0;i<3;i++)
     {
      Print(((CMyclass*)base.GetNodeAtIndex(i)).x," : ",((CMyclass*)base.GetNodeAtIndex(i)).y);
     }
   delete base;
  }
//+------------------------------------------------------------------+

...

Qu'avons-nous obtenu avec ce wrapper ? Un dynamic_cast inutile alors qu'il n'est absolument pas nécessaire ? Le wrapper lui-même a une conversion explicite en CMyClass. C'est-à-dire qu'il a une charge de travail de 0% alors que le code est plus compliqué (l'opérateur de référence d'index est utilisé comme un opérateur de cast explicite pour la classe passée - enfin, ce n'est pas évident du tout).

 
Ilya Malev:
P.S.S. Quoi qu'il en soit, les for ont l'air plutôt tristes ici - lorsque vous travaillez avec des listes, vous devriez utiliser des boucles comme for each (comme ma boucle)

Désolé, mais c'est stupide.

 
Vasiliy Sokolov:

Ce que vous avez écrit est juste une utilisation implicite de la même chose :

C'est à dire un tel pointeur anonyme, mais fondamentalement juste du sucre syntaxique. Il n'y a presque pas de sucre dans MQL, donc vous ne pouvez pas le faire de cette façon. Mais je dois souligner que le casting vers le descendant se fait sans aucune vérification ni conversion, donc on ne voit pas pourquoi le travail explicite avec le pointeur est si gênant.

Oui, je comprends, je suis toujours confus avec la syntaxe en MQL lorsque je travaille avec des pointeurs, cela semble être la même chose qu'en C++ standard, mais je suis constamment confus et je ne peux ni écrire quelque chose immédiatement, ni lire le code de la bibliothèque du paquet standard MT.... correctement. J'ai arraché tous mes cheveux ! ... mais toujours sur le .opera ! )))) - Je me débrouillerai de toute façon ;)


Ilya Malev:

Il y a une différence, une petite différence. S'il y a un objet qui n'a pas été converti en myclass, sans dynamic_cast il y aura une erreur d'exécution, et avec cela vous obtiendrez juste NULL en retour. Ce qui provoquera de toute façon une erreur si vous l'adressez avec .x immédiatement.

Je comprends tout cela, et ce n'est pas une petite différence, je dirai sincèrement que le code d'un programmeur professionnel se distingue de celui d'un amateur par cette différence même - dans la vérification des erreurs critiques ...... bien qu'avec les tendances modernes dans les langages de programmation, cela a été simplifié pour les programmeurs moins doués en utilisant try except finally etc ;)

 
Vasiliy Sokolov:

Je suis désolé, mais c'est stupide.

Oh, s'il vous plaît.

 
Igor Makanu:

Oui, je comprends tout, je n'arrive pas à comprendre la syntaxe de MQL quand on travaille avec des pointeurs, il semble que ce soit la même que dans le C++ standard, mais je suis constamment confus et je ne peux ni écrire quelque chose tout de suite, ni lire correctement le code de la même bibliothèque à partir de la livraison standard MT..... J'ai arraché tous mes cheveux ! ... mais toujours sur le .opera ! )))) - trouvez la solution ;)

Prendre C++ comme point de référence dans le cas de MQL ne fonctionnera pas :) Le volume de ce qui est impossible dans MQL est beaucoup plus grand que le volume des constructions "compatibles". À mon avis, MQL ressemble plus à un C# très tronqué avec un manque total de sucre syntaxique.

 
Igor Makanu:

tout est clair, et ce n'est pas une petite différence, je dirai que le code du programmeur professionnel diffère de celui de l'amateur exactement dans cette différence - dans le contrôle des erreurs critiques ..... Bien qu'avec les tendances modernes dans les langages de programmation, cela s'est simplifié pour les programmeurs moins doués qui utilisenttry except finally et ainsi de suite ;)

En fait, Try/Catch est un sujet plus intéressant qu'il n'y paraît :) Dommage que ce ne soit pas dans MQL.