Erreurs, bugs, questions - page 1890

 
Комбинатор:
En C++, cela ne fonctionne également que si un pointeur vers une classe de base pointe vers son descendant.

Je ne sais pas ce que vous voulez dire par là, mais ce code :

class CLASS1
{
public:
  int i;  
};

class CLASS2 : public CLASS1 {};

int main() {
  CLASS1 _object;
  CLASS2 *_ptr = (CLASS2*)&_object;  
  _ptr->i = 1;

   return 0;
}

fonctionne en C++, ce que j'ai écrit plus haut. Et voici le même code (en considérant la syntaxe MQL) :

class CLASS1
{
public:
  int i;  
};

class CLASS2 : public CLASS1 {};

int OnInit() {
  CLASS1 _object;
  CLASS2 *_ptr = dynamic_cast<CLASS2 *>(&_object);
  
  _ptr.i = 1;

   return 0;
}
ne fonctionne plus car _ptr devient NULL
Ce qui amène à se demander s'il s'agit d'un bogue dans MQL et s'il sera corrigé ou s'il restera ainsi.
 
Renat Fatkhullin:

C'est vrai, on ne peut pas conduire de bas en haut, seulement de haut en bas. C'est pour des raisons de sécurité.

Vous ne pouvez pas comparer avec le C++ - tout peut être réduit à n'importe quoi là-bas.


Je l'ai maintenant, merci pour la clarification ;))
 
Konstantin:

Je ne sais pas ce que vous voulez dire par là, mais ce code :

Essayez de le comprendre. Commencez par faire fonctionner dynamic_cast dans les plus. Si vous vous débrouillez tout seul, vous serez bien mieux loti.
 
Renat Fatkhullin:

C'est vrai, on ne peut pas conduire de bas en haut, seulement de haut en bas.

Que voulez-vous dire, vous ne pouvez pas être casté d'une classe de base à une descendante ?
 
Комбинатор:
Vous voulez dire que vous ne pouvez pas faire un cast d'une classe de base vers une classe descendante ?

Oui, dans le cas où la classe de base n'a pas de descendant réellement construit.

 
Renat Fatkhullin:

C'est vrai, on ne peut pas conduire de bas en haut, seulement de haut en bas. C'est pour des raisons de sécurité.

Si nous amenons le pointeur de haut en bas, c'est-à-dire vers le parent, et que nous le passons ensuite ailleurs dans l'étendue, les champs du descendant sont-ils disponibles à cet endroit ?
 
Renat Fatkhullin:

Oui.

Renate, savez-vous ce qu'est le dynamic_cast ?
 
Комбинатор:
Renat, savez-vous ce qu'est le dynamic_cast ?

Bien sûr.

Regardez le morceau de code MQL5 discuté. Une instance de base est créée, puis elle tente héroïquement de la convertir en descendante via dynamiccast, en violation de la sécurité. Eh bien, c'est une déception, bien sûr.

 

Le même exemple est directement abordé et expliqué dans la documentation. Le cast dynamique au moment de l'exécution n'est déclenché qu'après vérification du système de sécurité et de l'admissibilité des conversions. Chaque objet MQL5 possède toutes les méta-informations permettant de vérifier les droits au moment de l'exécution. Ce n'est pas du C++ vide.


Conversion dynamique de type à l'aide de l'opérateur dynamic_cast

Il est possible d'effectuer un casting dynamique des types à l'aide de l'opérateur dynamic_cast, qui ne peut être appliqué qu'aux pointeurs de classe. Dans ce cas, le contrôle de l'exactitude des types est effectué au moment de l'exécution du programme. Cela signifie que lorsque l'opérateur dynamic_cast est utilisé, le compilateur ne vérifie pas le type de données utilisé pour la conversion. Si la conversion d'un pointeur vers un type de données, qui n'est pas le type d'objet réel, est effectuée, le résultat sera NULL.

dynamic_cast<type-id> ( expression )

Le paramètre type-id entre crochets doit être un pointeur vers un type de classe précédemment défini . Letype d'opérande de l'expression (contrairement à C++) peut être n'importe quoi sauf void.

Exemple :

classe CBar { };
classe CFoo :public CBar { };

voidOnStart( )
{
Le bar CBar;
//--- le transfert dynamique du type de pointeur *bar vers le pointeur *foo est autorisé.
CFoo *foo =dynamic_cast<CFoo*>(&bar) ;//--- pas d'erreur critique d'exécution
Imprimer(foo) ;// foo=NULL
//--- Il est interdit d'essayer explicitement de convertir une référence de l'objet Bar en un objet Foo.
foo=(CFoo *)&bar ;// une erreur d'exécution critique se produira
Imprimer(foo) ;// cette ligne ne sera pas exécutée
}

 
Renat Fatkhullin:

Bien sûr.

Vous êtes sûr ? Parce que dynamic_cast est le plus souvent utilisé pour la conversion ascendante, du parent à la descendance.

De plus, dans MQL, il coule parfaitement de bas en haut, même quand il ne devrait pas :

class A
{
public:
   virtual void f()
   {
      Print("1");
   }
};

class B: public A
{
public:
   virtual void f()
   {
      Print("2");
   }
};

void OnStart()
{
   A* ptr1 = new B();
   ptr1.f();
   A* ptr2 = new A();
   ptr2.f();
   
   B* casted = dynamic_cast<B*>(ptr1);
   casted.f();
   
   B* casted1 = dynamic_cast<B*>(ptr2);
   casted1.f(); // здесь должна быть ошибка потому что casted1 должен быть null
   delete ptr1;
   delete ptr2;
}

вывод:
2017.05.13 18:30:14.864    t ETHUSD,M5: 2
2017.05.13 18:30:14.865    t ETHUSD,M5: 1
2017.05.13 18:30:14.866    t ETHUSD,M5: 2
2017.05.13 18:30:14.867    t ETHUSD,M5: 2


Renat Fatkhullin:

Jetez un coup d'œil au fragment de code MQL5 discuté.

Oui, cela ne devrait pas fonctionner et c'est déjà expliqué ci-dessus, mais pas parce que le casting ascendant est impossible.

Raison: