Erreurs, bugs, questions - page 1206

 
A100:

Une unification est nécessaire pour que le même code fonctionne aussi bien avec C++ qu'avec MQL. En C++, cet ordre est fait ( !) pour une raison. Au départ, j'ai pensé que le compilateur C++ était illogique et/ou avait un bug, mais maintenant je suis enclin à croire qu'il existe une raison objective pour une telle approche. Voici un exemple en MQL qui montre que X: : g est une correspondance complète, mais que Y::g est quand même appelé - comme en C++, ce qui contredit l'exemple précédent

Résultat : 3

Il s'avère que le C++ a un ordre "illogique" mais sans ambiguïté, tandis que MQL a un ordre aléatoire - lorsque les types correspondent exactement, la classe de base est appelée dans un cas et une classe dérivée dans un autre.

De quelle implémentation C++ parlez-vous exactement ? Dans quelle mesure cette mise en œuvre correspond-elle à la norme C++ ? Que dit la norme C++ sur le choix des fonctions surchargées ?

En fait, la surcharge de fonctions que vous décrivez est une conséquence d'une conception incorrecte.

Le portage du code source est un mythe. Seul le programme de test fonctionne de la même manière dans différents environnements C++. Le programme réel (nous parlons de milliers de lignes de code avec une valeur d'application réelle) fonctionnera différemment, du moins sous certains aspects, dans différents environnements. Et il n'est pas du tout question d'unifier MQL avec C++ - c'est un gaspillage du patrimoine génétique...

 
A100:

Une unification est nécessaire pour que le même code fonctionne aussi bien avec C++ qu'avec MQL. En C++, cet ordre est fait ( !) pour une raison (sinon il y a des ambiguïtés à un moment donné). A l'origine, je pensais que le compilateur C++ était illogique et/ou avait un bug, mais maintenant je suis enclin à croire qu'il existe des raisons objectives pour une telle approche. Voici un exemple en MQL, qui montre que X: : g est une correspondance complète, mais que Y::g est quand même appelé - comme en C++, ce qui contredit l'exemple précédent https://www.mql5.com/ru/forum/1111/page1223#comment_1074757.

Résultat : 3

Il s'avère que le C++ a un ordre "illogique" mais sans ambiguïté et que MQL a un ordre aléatoire - en cas de correspondance exacte des types, une classe de base est appelée dans un cas et une classe dérivée dans un autre cas.

Vous semblez vous tromper dans cet exemple, si la classe Y est héritée de X et non de C, alors le comportement serait le même que dans l'exemple précédent.
 
stringo:

Que dit la norme C++ sur l'ordre de sélection des fonctions surchargées ?

Pour citer Strawstrup : "Le C++ exige une correspondance de type exacte entre la fonction virtuelle dans la classe de base et la fonction substituée dans la classe dérivée".

J'ai maintenant examiné le problème et je suis arrivé à la conclusion que C++ est correct. Dans les deux exemples ci-dessus, g() de la classe dérivée cache (plutôt que de se substituer) à g() de la classe de base. Et le mécanisme de virtualité n'est activé que lorsque la substitution a lieu, et la substitution exige une correspondance exacte des types (sauf pour le type de retour). Seule la précision du type de retour peut dépendre de l'implémentation particulière.

 
mql5:
Vous semblez vous tromper dans cet exemple, si la classe Y est héritée de X plutôt que de C, le comportement serait le même que dans l'exemple précédent.

Oui, je me suis trompé ici, il s'avère que C++ et MQL ont tous deux des ordres de substitution et de dissimulation non ambigus, mais différents. Veuillez consulter mes arguments dans le post précédent sur la différence entre substitution et dissimulation.

Le fait que le C++ génère un avertissement lors du masquage vous indique que cet ordre est choisi intentionnellement.

class A {};
class B : public A {};

class X {
public:
        virtual int g( A* a )
        virtual int f( B* a )
};
class Y : public X {
public:
        virtual int g( A* a ) //подмена  X::g
        virtual int f( A* a ) //сокрытие X::f
};
 
A100:

Oui, je me suis trompé ici, il s'avère que C++ et MQL ont tous deux des ordres de substitution et de dissimulation non ambigus, mais différents. Veuillez consulter mes arguments dans le post précédent concernant la différence entre substitution et dissimulation.

Le fait que le C++ génère un avertissement en cas de dissimulation indique que cet ordre est choisi intentionnellement.

Le compilateur MQL, lorsqu'il recherche une méthode (fonction), ne considère pas le passage à un parent comme un casting, comme il semble le faire avec le C++ de MS, par exemple.

Merci pour le post, nous allons en discuter (y réfléchir).

 
mql5:
Le compilateur MQL, lorsqu'il recherche une méthode (fonction), ne considère pas le passage à un parent comme un casting, comme il semble le faire avec MS C++ par exemple.

Merci pour le message, nous allons en discuter (y réfléchir).

Notez que pas seulement de MS - j'ai utilisé Borland C++ 5.5.1

Stroustrup écrit qu'autrement, il peut y avoir des conséquences désagréables liées au fait d'"aller au-delà de la fin de l'objet de la classe".

 
A100:

Pour citer Strawstrup : "Le C++ exige une correspondance de type exacte entre la fonction virtuelle dans la classe de base et la fonction substituée dans la classe dérivée".

J'ai maintenant examiné le problème et je suis arrivé à la conclusion que C++ est correct. Dans les deux exemples ci-dessus, g() de la classe dérivée cache (plutôt que de se substituer) à g() de la classe de base. Et le mécanisme de virtualité n'est activé que lorsque la substitution a lieu, et la substitution exige une correspondance exacte des types (sauf pour le type de retour). Seule la précision du type de retour peut dépendre de l'implémentation particulière.

Attends une minute, attends une minute. Il s'agit de surcharger des fonctions avec des paramètres différents.

Les fonctions virtuelles, en revanche, ont toujours des paramètres du même type. Les fonctions virtuelles sortent du cadre de cette discussion

 
A100:

Notez que pas seulement de MS - j'ai utilisé Borland C++ 5.5.1

Stroustrup écrit qu'autrement, il peut y avoir des conséquences désagréables liées au fait de "dépasser la fin de l'objet de la classe".

Nous en avons discuté ; nous n'allons pas changer le comportement du compilateur MQL - c'est un "bâton à deux tranchants". Laissez-moi vous expliquer.

Le problème ne se pose que lorsque des modifications sont apportées aux classes prêtes à l'emploi (dans un programme de travail).
Une fois que le parent a une fonction plus appropriée, le programme s'arrête soudainement de fonctionner, car au lieu de la méthode du descendant, la méthode du parent a été appelée.
Eh bien, si nous changeons le comportement de MQL, alors une situation similaire peut se produire - lors de l'ajout d'une nouvelle méthode au descendant, au lieu de la fonction parent (sans casting des paramètres) la méthode du descendant est appelée, et avec le casting des paramètres, et le programme cesse de fonctionner à nouveau.

Ainsi, aucun problème autre que la compatibilité avec le C++ ne sera résolu, de plus, le changement de comportement du compilateur affectera les programmes MQL existants.
 

Так как переменные типа структур и простых типов не имеют указателей, то применять к ним функцию GetPointer() запрещено.

Il est également interditde passer un pointeurcomme argument à une fonction (laquelle ?? ? ?GetPointer ou une autre ?).Dans tous ces cas, le compilateur signalera une erreur.

Citation de la documentation.

class A{
public:
   void operator= (const A* from){
      if (GetPointer(this) == GetPointer(from))      // а тут я передаю и все ок
         Alert(1);                                  // резутат 1  из за того что передаю this
      else
         Alert(2);
   }
};

class B : public A{
public:
   void operator= (const B& from){  
      if (GetPointer(this) == GetPointer(from))
         return;
      operator=((A*)(GetPointer(this)));
   }
};
  B b;
   B bb;                        // забыл написать создание объектов и вызов функции.
   b = bb;

J'ai déjà compris pourquoi il ne s'agit pas de gronder les alertes - c'est ma faute si j'ai passé un mauvais pointeur dans une fonction.

 
ALXIMIKS:

Il est également interdit de passer un pointeur comme argument à une fonction (qui ? ?? GetPointer ou tout autre ? ??).

Vous devez faire référence à un pointeur vers une structure et/ou un type simple (ce n'est pas explicitement indiqué ici, mais le contexte l'implique). Il y a même un pointeur vers une classe comme argument de fonction dans l'exemple ci-dessous

class CItem
  {
   CItem*            m_next;
   void              Next(CItem *item) { m_next=item; }
  };

Et si GetPoiner() était visé spécifiquement, votre exemple n'a aucune autre possibilité de convertir un pointeur d'un pointeur vers un objet (autre que celle que vous avez utilisée), donc cette interdiction n'a aucun sens

//даже такую запись сложно запретить
GetPointer(GetPointer(GetPointer(GetPointer(from))))
Raison: