Conversion de Type

Conversion des Types Numériques

Il est souvent nécessaire de convertir un type numérique dans un autre type. Tous les types numériques ne peuvent pas être convertis dans un autre type. Voici le schéma de conversion autorisée :

Schéma de conversion de type possible

Les lignes fléchées pleines indiquent les changements qui sont effectués pratiquement sans perte d'information. Au lieu du type char, le type bool peut être utilisé (les deux ne prennent qu'un octet en mémoire), au lieu du type int, le type color peut être utilisé (4 octets), au lieu du type long, datetime peut être utilisé (prend 8 octets). Les 4 lignes grises pointillées, également fléchées, dénotent une conversion lorsque une perte de précision peut se produire. Par exemple, le nombre de chiffres dans l'entier 123456789 (int) est supérieur au nombre de chiffres pouvant être représentés par un float.

   int n=123456789;
   float f=n;    // le contenu de f est égal à 1.234567892E8
   Print("n = ",n,"   f = ",f);
   // résultat n= 123456789    f= 123456792.00000

Un nombre converti en float a le même ordre, mais est moins précis. Les conversions, contrairement aux flèches noires, peuvent être effectuées avec une perte possible d'information. Les conversions entre char et uchar, short et ushort, int et uint, long et ulong (conversions dans les 2 sens) peut amener à une perte de données.

La partie fractionnelle est toujours supprimée lors de la conversion des valeurs à virgule flottante vers un type entier. Si vous souhaitez arrondir un float au nombre entier le plus proche (ce qui est plus pratique dans de nombreux cas), vous devriez utiliser la fonction MathRound().

Exemple :

//--- Accélération gravitationnelle
   double g=9.8;
   double round_g=(int)g;
   double math_round_g=MathRound(g);
   Print("round_g = ",round_g);
   Print("math_round_g = ",math_round_g);
/*
  Résultat :
   round_g = 9
   math_round_g = 10
*/

Si deux valeurs sont combinées avec un opérateur binaire, l'opérande du type le plus bas est converti dans le type le plus haut avant l'exécution de l'opération selon la priorité donnée dans le schéma ci-desous :

Conversion durant la phase de link par une opération binaire

Les types de données char, uchar, short, et ushort inconditionnellement sont convertis vers le type int.

Exemples :

   char   c1=3;
//--- Premier exemple
   double d2=c1/2+0.3;
   Print("c1/2 + 0.3 = ",d2);
// Résultat :   c1/2+0.3 = 1.3
 
//--- Deuxième exemple
   d2=c1/2.0+0.3;
   Print("c1/2.0 + 0.3 = ",d2);
// Résultat :   c1/2.0+0.3 = 1.8

L'expression calculée consiste en 2 opérations. Dans le premier exemple, la variable c1 de type char est convertie dans une variable temporaire de type int, car la deuxième opérande dans la division, la constante 2, est du type supérieur int. Le résultat de la division entière 3/2 donne la valeur 1, qui est de type int.

Dans la 2ème opération du premier exemple, la deuxième opérande est la constante 0.3, qui est de type double, le résultat de la première opération est donc converti dans une variable temporaire de type double avec la valeur 1.0.

Dans le deuxième exemple, la variable de type char c1 est convertie dans une variable temporaire de type double, car la deuxième opérande de la division, la constante 2.0, est de type double ; aucun autre conversion n'est faire.

 

Conversion des Types Numériques

Dans les expressions du langage MQL5, les conversions de type explicites et implicites peuvent être utilisées. La conversion de type explicite est écrit comme suit :

var_1 = (type)var_2;

Le résultat de l'éxecution d'une expression ou d'une fonction peut être utilisé dans la variable var_2. La notation comme une fonction de la conversion explicite de type est également possible :

var_1 = type(var_2);

Considérons une conversion explicite de type basée sur le premier exemple.

//--- Troisième exemple
   double d2=(double)c1/2+0.3;
   Print("(double)c1/2 + 0.3 = ",d2);
// Résultat :   (double)c1/2+0.3 = 1.80000000

Avant que la division soit effectuée, la variable c1 est convertie explicitement vers le type double. La constante entière 2 est maintenant convertie dans la valeur 2.0 de type double, car suite à la conversion, la première opérande a pris le type double. En fait, la conversion explicite de type explicite est une opération unaire.

En outre, lors de la tentative de conversion de type, le résultat peut aller au-delà de l'intervalle autorisé. Dans ce cas, le résultat est tronqué. Par exemple :

   char c;
   uchar u;
   c=400;
   u=400;
   Print("c = ",c); // Résultat c=-112
   Print("u = ",u); // Résultat u=144

Avant que les opérations (exceptées les affectations) ne soient effectuées, les données sont converties dans le type de priorité maximum. Avant que les affectations ne soient effectuées, les données sont converties dans le type cible.

Exemples :

   int    i=1/2;        // aucune conversion de type, le résultat est 0
   Print("i = 1/2  ",i);
 
   int k=1/2.0;         // l'expression est convertie dans le type double,
   Print("k = 1/2  ",k);  // et est ensuite convertie dans le type int cible, le résultat est 0
 
   double d=1.0/2.0;    // aucune conversion de type, le résultat est 0.5
   Print("d = 1/2.0; ",d);
 
   double e=1/2.0;      // l'expression est convertie dans le type double,
   Print("e = 1/2.0; ",e);// qui est le même type que le type cible, le résultat est 0.5
 
   double x=1/2;        // l'expression de type int est convertie vers le type cible double
   Print("x = 1/2; ",x);  // le résultat est 0.0

Lors de la conversion du type long/ulong en double, la précision peut être perdue si la valeur entière est supérieure à 9223372036854774784 ou inférieure à -9223372036854774784.

void OnStart()
  {
   long l_max=LONG_MAX;
   long l_min=LONG_MIN+1;
//--- définit la valeur entière la plus haute, qui ne perdra pas de précision lors de la conversion en double
   while(l_max!=long((double)l_max))
      l_max--;
//--- définit la plus petite valeur entière, qui ne perdra pas de précision lors de la conversion en double
   while(l_min!=long((double)l_min))
      l_min++;
//--- déduit l'intervalle trouvé pour les valeurs entières  
   PrintFormat("Lors de la conversion d'une valeur entière en double, elle doit être "
               "dans l'intervalle [%I64d, %I64d]",l_min,l_max);
//--- maintenant, voyons ce qui se passe si la valeur passe en dehors de cet intervalle
   PrintFormat("l_max+1=%I64d, double(l_max+1)=%.f, ulong(double(l_max+1))=%I64d",
               l_max+1,double(l_max+1),long(double(l_max+1)));
   PrintFormat("l_min-1=%I64d, double(l_min-1)=%.f, ulong(double(l_min-1))=%I64d",
               l_min-1,double(l_min-1),long(double(l_min-1)));
//--- reçoit le résultat suivant
// Lors de la conversion d'une valeur entière en double, elle doit être dans l'intervalle [-9223372036854774784, 9223372036854774784]
// l_max+1=9223372036854774785, double(l_max+1)=9223372036854774800, ulong(double(l_max+1))=9223372036854774784
// l_min-1=-9223372036854774785, double(l_min-1)=-9223372036854774800, ulong(double(l_min-1))=-9223372036854774784
  }

 

Conversion du Type String

Le type string a la plus haute priorité parmi les types simples. Si l'un des opérandes d'une opération est du type string, la seconde opérande sera donc convertie en string automatiquement. Notez que pour une string, l'addition est possible. La conversion explicit d'une string vers n'importe quel type numérique est permise.

Exemples :

   string s1=1.0/8;            // l'expression est convertie du type double,
   Print("s1 = 1.0/8; ",s1);     //  vers le type string,
// le résultat est "0.12500000" (une chaîne de 10 caractères)
 
   string s2=NULL;             // déinitialisation de la chaîne
   Print("s2 = NULL; ",s2);      // le résultat est une chaîne vide
   string s3="Ticket N"+12345; // l'expression est convertie en string
   Print("s3 = \"Ticket N\"+12345",s3);
 
   string str1="true";
   string str2="0,255,0";
   string str3="2009.06.01";
   string str4="1.2345e2";
   Print(bool(str1));
   Print(color(str2));
   Print(datetime(str3));
   Print(double(str4));

 

Conversion des Pointeurs de Classes de Base vers des Pointeurs de Classes Dérivées

Les objets d'une classe ouverte générée peuvent également être vues comme des objets de la classe de base correspondante. Ceci conduit à des conséquences intéressantes. Par exemple, en dépit du fait que des objets de classes différentes, générés pour une même classe de base, peut différer significativement les uns des autres, nous pouvons créer une liste chaînée (List) de ces objets, puisqu'ils peuvent être vus comme des objets du type de base. Mais l'inverse n'est pas vrai : des objets de la classe de base ne sont pas automatiquement des objets d'une classe dérivée.

Vous pouvez utiliser une conversion explicite pour convertir des pointeurs de la classe de base en pointeurs d'une classe dérivée. Mais vous devez être totalement sûr de la possibilité d'une telle transformation, car sinon une erreur d'exécution critique se produira et le programme mql5 sera stoppé.

Conversion dynamique avec l'opérateur dynamic_cast operator #

La conversion dynamique est effectuée avec l'opérateur dynamic_cast qui ne peut être appliqué que sur des pointeurs de classes. La validation du type est effectué pendant l'exécution. Cela signifie que le compilateur ne vérifie pas le type de donnée appliqué pour la conversion lorsque l'opérateur dynamic_cast est utilisé. Si un pointeur est converti dans un type de données qui n'est pas le type réel d'un objet, le résultat est NULL.

dynamic_cast <type-id> ( expression )

Le paramètre type-id entre crochets doit pointer vers une classe définie auparavant. Contrairement au C++, le type de l'opérande expression peut être de n'importe quelle valeur sauf pour void.

Exemple :

class CBar { };
class CFoo : public CBar { };
 
void OnStart()
  {
   CBar bar;    
//--- conversion dynamique du type du pointeur *bar vers le pointeur *foo est autorisée
   CFoo *foo = dynamic_cast<CFoo *>(&bar); // pas d'erreur critique
   Print(foo);                             // foo=NULL      
//--- la tentative de convertir explicitement une référence d'objet de type Bar vers un objet de type Foo est interdite
   foo=(CFoo *)&bar;                       // erreur runtime critique
   Print(foo);                             // cette chaîne n'est pas exécutée
  }

Voir aussi

Types de Données