OLP. Problèmes d'application - page 11

 
Interesting:

Comme c'est bon de pouvoir lire... :)

Ce n'est pas non plus une mauvaise approche, bien que, si j'ai bien compris, ces deux approches soient calculées sur le transfert/la lecture d'un seul paramètre (bien que de types différents).

Mais comment résoudre le problème, lorsque vous avez beaucoup de paramètres et que vous ne pouvez pas tous les mettre dans une classe de base ?

Si je comprends bien, vous devez entrer un index du paramètre que vous passez (vous pouvez aussi créer un tableau dans une classe avec les paramètres stockés par index) ?

Je ne le comprends pas non plus...

Dans mon exemple, il y a un index, mais il n'est pas numérique sous une forme explicite, mais un enum.....

 

Oublie ça, ça n'en vaut pas la peine.

 

Interesting:

Yedelkin:

En général, après une discussion sur le problème,https://www.mql5.com/ru/forum/3566/page6#comment_58280 a envoyé une demande au SR.

1. Je ne sais pas, je ne sais pas.

Je ne pense pas que les développeurs prendront certaines mesures, sacrifiant la fonctionnalité au nom de la sécurité (à juste titre d'ailleurs).

Faire un rapport.

L'application était la suivante :
...

Suggestion :

1. Clarifier la section "Polymorphisme" du manuel "Polymorphisme" en termes de spécification de la façon de remplir correctement les formes de tableau [10] avec des instances de classes dérivées de CShape (donner un exemple).

2. Vérifiez si la chaîne de caractères est écrite correctement :

CShape[10] shapes;                       // массив объектов CShape

3. Expliquez s'il faut ou non mettre des accolades immédiatement après le nom de la classe déclarée lors de la déclaration des classes :

classe CShape{} ;

classe CCircle{} :public CShape

classe CSquare{} :public CShape

Réponse :

Rashid Umarov 2011.04.11 15:17

Au moment de la rédaction de l'aide, certains points n'étaient pas encore clairs pour la documentation. Nous allons corriger ce point et ajouter le code correct. Merci pour votre message.

Une description détaillée sera ajoutée à l'aide, dont voici un extrait :

Nous supposons que notre programme utilise des objets de types différents (CCircle et CSquare) mais hérités d'un type de base CShape. Le polymorphisme nous permet de créer un tableau d'objets de type de base CShape, mais lorsque nous déclarons ce tableau, les objets eux-mêmes sont encore inconnus et leur type est indéfini.

La décision du type d'objet qui sera contenu dans chaque élément du tableau sera prise pendant l'exécution du programme. Cela implique la création dynamique d'objets pour les classes correspondantes et, par conséquent, la nécessité d'utiliser des pointeurs d'objets au lieu des objets eux-mêmes.

Pour créer des objets de façon dynamique, on utilise l'opérateur new ; chacun de ces objets doit être indépendamment et explicitement supprimé par l'opérateur delete. Par conséquent, nous allons déclarer un tableau de pointeurs de type CShape et créer un objet du type requis pour chacun de ses éléments(nom_de_la_classe_nouvelle), comme il est indiqué dans le script d'exemple :

//+------------------------------------------------------------------+

//| Script program start function                                    |

//+------------------------------------------------------------------+

void OnStart()

  {

//--- объявим массив указателей объектов базового типа 

   CShape *shapes[5];   // массив указателей на объекты CShape



//--- здесь заполняем массив производными объектами

//--- объявим указатель на объект типа CCircle

   CCircle *circle=new CCircle();

//--- задаем свойства объекта по указателю circle

   circle.SetRadius(2.5);

//--- поместим в shapes[0] значение указателя

   shapes[0]=circle;



//--- создаем еще один объект CCircle и запишем его указатель в shapes[1]

   circle=new CCircle();

   shapes[1]=circle;

   circle.SetRadius(5);



//--- тут мы намеренно "забыли" задать значение для shapes[2]

//circle=new CCircle();

//circle.SetRadius(10);

//shapes[2]=circle;



//--- для неиспользуемого элемента установим значение NULL

   shapes[2]=NULL;



//--- создаем объект CSquare и запишем его указатель в shapes[3]

   CSquare *square=new CSquare();

   square.SetSide(5);

   shapes[3]=square;



//--- создаем объект CSquare и запишем его указатель в shapes[4]

   square=new CSquare();

   square.SetSide(10);

   shapes[4]=square;



//--- массив указателей есть, получим его размер

   int total=ArraySize(shapes);

//--- пройдем в цикле по всем указателям в массиве 

   for(int i=0; i<5;i++)

     {

      //--- если по указанному индексу указатель является валидным

      if(CheckPointer(shapes[i])!=POINTER_INVALID)

        {

         //--- выведем в лог тип и площадь фигуры

         PrintFormat("Объект типа %d имеет площадь %G",

               shapes[i].GetType(),

               shapes[i].GetArea());

        }

      //--- если указатель имеет тип POINTER_INVALID

      else

        {

         //--- сообщим об ошибке

         PrintFormat("Объект shapes[%d] не инициализирован! Его указатель %s",

                     i,EnumToString(CheckPointer(shapes[i])));

        }

     }



//--- мы должны самостоятельно уничтожить все созданные динамические объекты

   for(int i=0;i<total;i++)

     {

      //--- удалять можно только объекты, чей указатель имеет тип POINTER_DYNAMIC

      if(CheckPointer(shapes[i])==POINTER_DYNAMIC)

        {

         //--- сообщим об удалении

         PrintFormat("Удаляем shapes[%d]",i);

         //--- уничтожим объект по его указателю

         delete shapes[i];

        }

     }

  }


Notez que lorsque vous supprimez un objet avec l'opérateur delete, vous devez vérifier le type de son pointeur. Vous pouvez supprimer uniquement les objets avec le pointeur POINTER_DYNAMIC, vous obtiendrez une erreur pour les pointeurs d'un autre type.

Je pense que cet exemple couvre complètement l'idée de créer un tableau de pointeurs.
Rashid Umarov 2011.04.11 10:31

Merci pour le post, nous avons corrigé №2 et №3. Sera dans les nouvelles versions de l'aide



 

Question. La bibliothèque standard utilise les lignes suivantes

void CTrade::Request(MqlTradeRequest& request) const
  {...}

Le Manuel de référence dit : " le spécificateur const n'est pas applicable aux membres des structures et des classes". Que signifie l'utilisation de const dans une méthode de classe ci-dessus, et quelles sont les règles pour l'utiliser dans de tels cas ?

Документация по MQL5: Стандартная библиотека
Документация по MQL5: Стандартная библиотека
  • www.mql5.com
Стандартная библиотека - Документация по MQL5
 

Yedelkin:

...............

Que signifie l'utilisation ci-dessus de const dans une méthode de classe, et quelles sont les règles pour l'utiliser dans de tels cas ?

Oh oui, ça fait longtemps que je me pose la question aussi. Je veux utiliser la langue de manière significative, en étant pleinement conscient des "règles du jeu".
 
Yedelkin:

Question. La bibliothèque standard utilise les lignes suivantes

Le Manuel de référence dit : " le spécificateur const n'est pas applicable aux membres des structures et des classes". Que signifie l'utilisation de const dans une méthode de classe ci-dessus, et quelles sont les règles pour l'utiliser dans de tels cas ?

Un membre de structure/classe est une chose, mais une méthode en est une autre.

Une méthode décrite comme const signifie qu'elle ne change pas l'état/les membres de sa classe. C'est-à-dire qu'après avoir appelé une telle méthode, l'état interne de la classe reste inchangé. Il est utilisé pour indiquer en plus au compilateur de vérifier les tentatives de modification des membres de la classe.

 
Renat:

Un membre de structure/classe est une chose et une méthode en est une autre.

Une méthode décrite comme const signifie qu'elle ne change pas l'état/les membres de sa classe. C'est-à-dire que l'état interne de la classe reste inchangé après l'appel de cette méthode. Il est utilisé pour indiquer en plus au compilateur de vérifier les tentatives de modification des membres de la classe.

Wow. Merci ! Et je me suis creusé les méninges.

 
TheXpert:
Au fait, une question logique tant que nous sommes sur le sujet : il n'y a pas de manuel et ce n'est pas prévu ?

Comment pourrait-on l'utiliser ? Parce que les fils n'interagissent pas entre eux,

Si les données pouvaient être transférées librement d'un thread à l'autre, alors, oui, une telle instruction serait nécessaire.

 
Mince, je pensais que j'écrivais quelque chose de mal :) maintenant je sais ce que c'est. Pas volatile bien sûr -- mutable:))
 
class COracleTemplate
  {
private:
public:
   string            filename;
                     COracleTemplate(){Init();};
                    ~COracleTemplate(){DeInit();};
   virtual void      Init(){filename=this.Name();Print("loadSettings from ",filename);};
   virtual void      DeInit(){Print("saveSettings to ",filename);};
   virtual string    Name(){return("Prpototype");};
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CCO2:public COracleTemplate
  {
   virtual string    Name(){return("CO2");};
  };
class CH2O:public COracleTemplate
  {
   virtual string    Name(){return("H2O");};
  };
COracleTemplate* CO2,*H2O;
void OnStart()
  {
   CO2=new CCO2;
   Print(CO2.Name()," filename=",CO2.filename);
   delete CO2;
   
   H2O=new CH2O;
   Print(H2O.Name()," filename=",H2O.filename);
   delete H2O;
   
  }

Bon après-midi.

Une telle question.

Sur le code ci-dessus

Qu'est-ce que j'ai fait de mal ou est-ce généralement irréalisable dans MT5 ?

Je veux (comme je pense que c'est évident) - obtenir des noms surchargés dans les variables de nom de fichier...