Bogue de compilation avec le paramètre template = void* - page 6

 
Alexey Navoykov:

Tout fonctionne bien, pourquoi inventez-vous ça ?

Dans le journal, on obtient :

void A::~A()
void B::~B()

Pourquoi suis-je tombé dans le panneau...

Alors je suis désolé, je ne savais pas que vous pouviez faire ça, MKL est très différent de C++. Du côté positif, la suppression de void* est UB.

 

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

Nouvelle version de MetaTrader 5 build 1930 : fenêtre graphique flottante et bibliothèque .Net dans MQL5

Alexey Navoykov, 2018.12.15 02:44

Chers développeurs. Plus tôt dans l'un des fils de discussion, nous avons discuté du défaut du compilateur qui permet le casting implicite d'une classe de base vers une classe dérivée, mais il semble que vous ne l'ayez pas remarqué. Il s'agit d'un problème sérieux, qui rend le contrôle des erreurs difficile et devient un casse-tête constant lors de l'utilisation active de la POO. Un tel casting devrait être seulement explicite. C'est une règle générale pour le C++ et le C#.

class A {  };

class B : public A { };

A* a = new A;

B* b = a;  // Нет ошибки компиляции!

void f(B*) {  }

void OnInit()
{ 
  f(a);  // Нет ошибки компиляции!
}  

Et que faire ici ?

class A {  };

class B : public A { };

A* a = new A;

void* v = a;

B* b = v;  // Нет ошибки компиляции!


Ce comportement doit-il également être considéré comme une erreur ?

 
Alexey Navoykov:

Si le styler rend le code difficile à lire, alors pourquoi l'utiliser ?

Pour moi, un stylo n'est bon que si TOUTES ses règles peuvent être personnalisées avec souplesse.

Ainsi, si vous lisez le code de quelqu'un d'autre sous une forme imprimée (ou sur un forum, comme ici).

 
fxsaber:
À propos des parenthèses
((A*)(b.GetPtr())).f(); // Доп. скобки, чтобы подчеркнуть, что именно имелось в виду, не полагаясь на приоритеты.

Eh bien, peut-être que cela vous mettra en valeur, mais pour moi, cela ne fera que m'embrouiller. En regardant cette expression, je ne peux pas comprendre immédiatement quelle méthode est appelée ici. Mais dans les deux lignes précédentes, c'est clair tout de suite.

Pour comprendre ce qui se passe, il faut ouvrir toutes les parenthèses. Plus il y a de parenthèses, plus on perd du temps à comprendre ce qui se passe, surtout si elles ne sont pas séparées par des espaces.

 
Alexey Navoykov:

Eh bien, peut-être que cela vous mettra en valeur, mais pour moi, cela ne fera que m'embrouiller. En regardant cette expression, je ne peux pas comprendre immédiatement quelle méthode est appelée ici. Mais dans les deux lignes précédentes, tout est clair d'un coup.

Pour comprendre exactement ce qui se passe, il faut ouvrir toutes les parenthèses. Plus il y a de parenthèses, plus on passe de temps à comprendre ce qui se passe, surtout si elles ne sont séparées par aucun espace.

Les parenthèses supplémentaires ne servent pas à la lecture - laissez le styliste s'en charger, en mettant des espaces.

Mais pour la maîtrise de soi pendant l'écriture. Pourquoi devrais-je me fier aux priorités de quelqu'un pour écrire dans un domaine sensible, tout en étant conscient que j'écris du code multiplateforme (et pas nécessairement seulement MT4/5) qui peut être porté dans d'autres langues ? Les parenthèses supplémentaires éliminent complètement l'influence des priorités linguistiques. Tout devient absolument sans ambiguïté. De ce fait, il y a une fiabilité à 100% que rien n'échouera dans cet endroit après la prochaine construction.


De plus, lorsque je lirai cette parenthèse, je devrai consacrer du temps à la compréhension absolue de ce que je veux dire ici. Et sur le sujet de la visibilité.

bool a = (1 < 2) && (3 < 4);
bool b = 1 < 2 && 3 < 4;

demandons nous, quelle option est la plus visuelle ?

 
fxsaber:

Ce comportement est-il également considéré comme une erreur ?

Bien sûr que oui. C'est la même chose.

Il s'avère donc que rien n'est généré là où un problème est vraiment possible et qu'il faut au moins des avertissements (voire une erreur de compilation). Mais ils ne font pas l'économie d'avertissements quand on nous impose des parenthèses ;) Et certains ici proposent même d'interdire la compilation sans parenthèses et menacent de nous gifler ;) C'est comme ça qu'on vit...

 
Alexey Navoykov:

Bien sûr. C'est la même chose.

Il s'avère donc que s'il y a un réel problème et qu'au moins un avertissement est nécessaire (ou même une erreur de compilation), rien n'est affiché. Mais avec des parenthèses, ils n'épargnent aucun avertissement ;) Et certaines personnes ici proposent même d'interdire la compilation sans parenthèses et menacent de vous frapper ;) C'est ainsi que nous vivons...

Vous avez donc besoin d'un avertissement aussi ? Quel genre de double standard est-ce là : dans les deux endroits, le comportement est sans ambiguïté, mais avec les parenthèses vous êtes contre les avertissements, et ici vous êtes pour ?

Vous avez besoin d'un avertissement pour ne pas faire des erreurs difficiles à trouver. La difficulté est donc une évaluation subjective. Avec les parenthèses, on ne fait pas d'erreurs, et ici, on peut en faire. Et pour moi, c'est vice versa.

Alors, pour lequel d'entre nous les règles d'émission des avertissements doivent-elles être adaptées ?

 
Ilya Malev:

Je ne connaissais pas StringConcatenate, c'est dommage que dans MT5 il a été remanié et ne peut pas être utilisé sans string s. Et le StringFormat est beaucoup plus rapide sur 4

Et en général, pour une raison quelconque, cette opération consistant à "sonder" un pointeur dans une chaîne de caractères est presque deux fois plus lente en 5, bien qu'en général, elle fonctionne plus rapidement dans ce cas, parfois d'un ordre.

il est possible que StringConcatenate() soit en 32 bits, vous ne savez pas, les développeurs ont déjà écrit que les méta-interprètes en 5 et 4 sont les mêmes, peut-être pour des raisons de compatibilité, ils l'ont "enveloppé".

Hier, j'ai essayé de résoudre votre problème avec dynamic_cast< >. Le problème est que MQL ne permet pas de déréférencer les pointeurs. la fonction dans une méthode de classe peut être appelée via dynamic_cast<C_myclass >( func( ) ), vous pouvez obtenir un pointeur vers la classe via dynamic_cast< > mais que faire avec un pointeur ? - vous pouvez réassigner void *ptr , mais cela n'a aucun sens puisque le pointeur ne peut pas être déréférencé de toute façon

 
pavlick_:

Si vous voulez mettre CArayObject au rebut, vous devez faire une surcharge (comme ceci https://www.mql5.com/ru/forum/170952/page110#comment_9894796) sur la classe de base et les mettre dans un tableau (éventuellement le vôtre), mais alors vous n'aurez plus besoin de void*.

Je ne suis pas contre le vide*, il est nécessaire, mais dans une capacité différente.

Je ne vois pas l'intérêt du code par référence (bien que je n'utilise pas non plus les bibliothèques standard). Si l'insertion d'un objet dans un tableau implique la création d'une copie de celui-ci, alors la méthode d'affectation ou le constructeur de copie doit être déclaré et décrit explicitement dans cette classe, sinon aucun wrapper ne sera utile de toute façon. Si vous avez seulement besoin de placer une référence à un objet dans un tableau, vous n'avez pas besoin de wrappers (pourquoi ?).

Au fait, vous semblez ignorer que if(p) delete p n'est pas identique à "if reference points to an existing dynamic object, delete it" en mql.

class A{};

void OnStart()
 {
  A *a=new A;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
  delete a;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
 }
 
fxsaber:

Et sur le sujet de la visibilité.

demandons-nous, lequel est le plus clair ?

Eh bien, si c'est comme ça que le styliste l'a formaté pour vous :

1 < 2 && 3 < 4;

alors, encore une fois, c'est au styliste de décider. Je ne ferais jamais ça dans mon code. Je le ferais de cette façon :

1<2 && 3<4
либо
1 < 2  &&  3 < 4