OLP. Problèmes d'application - page 4

 
Yedelkin:

Question. Une fois qu'une fonction virtuelle avec un ensemble spécifique de paramètres et de types est déclarée dans une classe parent, le nombre et les types de paramètres des fonctions virtuelles correspondantes peuvent-ils être modifiés dans les classes enfants ?

D'une part, le Manuel de référence indique qu'"une fonction virtuelle peut être substituée dans une classe dérivée . Lechoix de ladéfinition de fonction à appeler pour la fonction virtuelle est fait dynamiquement (au moment de l'exécution). Un cas typique est celui où une classe de base contient et les classes dérivées ont leurs propres versions de cette fonction". En revanche, les exemples donnés dans le Manuel de référence font référence à des cas où les fonctions virtuelles ont des corps de définition de fonction différents plutôt que des en-têtes de définition de fonction.

D'aussi loin que je me souvienne, c'est possible. Mais il faut faire très attention aux types et au nombre de paramètres.

Vous devez également faire attention aux types de valeurs transmises et aux valeurs par défaut.

Voici quelques exemples pour plus de simplicité.

Cette variante fera l'affaire.

boll MyFunction(int Param);
boll MyFunction(int Param1,int Param2);

Celui-ci ne fonctionne pas (ou plutôt, il fonctionnera peut-être, mais avec quelques bogues et certaines réserves).

//Ели второй параметр будет упущен, то компилятор может и не "понять" смысла всего задуманного
boll MyFunction(int Param);
boll MyFunction(int Param1,int Param2 = 0);
//Так тоже может не прокатить по причине совпадения типов у второго параметра
boll MyFunction(int Param1,color Param2);
boll MyFunction(int Param1,int Param2);

Il se passe exactement la même chose lorsque vous rechargez des méthodes à l'intérieur d'une classe.

 
mql5:
Une copie exacte de la définition, à l'exception des paramètres par défaut (les paramètres par défaut peuvent varier, mais il est préférable de ne pas les utiliser).
Voulez-vous dire "seulement une copie exacte de l'en-tête de la définition" ? Après tout, la définition de la fonction comprend l'en-tête et le corps. Les corps sont définitivement différents dans les exemples.
 

Intéressant, si je comprends bien, la virtualisation de fonctions et la surcharge de fonctions sont des choses légèrement différentes. Etmql5 dit que dans la virtualisation des fonctions, il doit y avoir une copie papier de l'en-tête de la fonction (je ne prends pas en compte les paramètres par défaut).

 
Yedelkin:

Intéressant, si je comprends bien, la virtualisation de fonctions et la surcharge de fonctions sont des choses un peu différentes. Etmql5 dit que dans la virtualisation des fonctions, il doit y avoir une copie papier de l'en-tête de la fonction (je ne prends pas en compte les paramètres par défaut).

> Question. Après la déclaration d'une fonction virtuelle avec un certain ensemble de paramètres et leurs types dans une classe mère, est-il possible de changer le nombre et les types de paramètres des fonctions virtuelles correspondantes dans les classes descendantes ?

Si je comprends bien, l'enfant doit surcharger la fonctionnalité de l'ancêtre.

Pour être franc, je ne me souviens pas avoir fait ce genre de choses avec virtual (je pense l'avoir fait), mais l'affirmation concernant la surcharge est vraie - j'ai moi-même fait cette erreur une fois.

PS

Si tout est fait correctement, comme je le comprends, le nombre de paramètres peut être augmenté ou diminué. Les difficultés seront si le nombre de paramètres reste le même, mais que leurs types sont modifiés...

 

Bref, j'ai esquissé cet exemple :

class C_A             //родительский класс
{
 public:
 virtual double function(double a1, double a2, double a3) { return; }
}
class C_B : public C_A
{
 public:
 virtual double function(double a1, double a2, double a3) { return(a1);   }
}
class C_C : public C_A
{
 public:      
 virtual double function(double a1, double a2, double a3) { return(a2);   }
        double function(double a1, double a2)           { return(a1+a2); }
}
//где-то в программе объявляем указатель
C_A  *pointer;
int random=rand()%2;
   switch(random)
     {
      case 0: pointer=new C_B; break;
      case 1: pointer=new C_C; break;
     }

//вызываем виртуальный метод
   if(pointer!=NULL)
     {
      pointer.function(a1,a2,a3);
     }

Il s'avère qu'indépendamment du fait qu'une méthode de fonction soit surchargée ou non dans la classe C_C, une fonction virtuelle peut être appelée avec seulement trois paramètres - pointeur.function(a1,a2,a3). Par conséquent, le programme n'atteindra jamais la méthode à deux paramètres de la classe C_C lors de l'appel des fonctions virtuelles. N'est-ce pas ?

 
Yedelkin:

Bref, j'ai esquissé cet exemple :

Il s'avère qu'indépendamment du fait qu'une méthode de fonction soit surchargée ou non dans la classe C_C, une fonction virtuelle peut être appelée avec seulement trois paramètres - pointeur.function(a1,a2,a3). Par conséquent, le programme n'atteindra jamais la méthode à deux paramètres de la classe C_C lors de l'appel des fonctions virtuelles. N'est-ce pas ?

Analysez ce que fait le programme en insérant dans les constructeurs et les destructeurs des impressions avec la macro __FUNCTION__, ce sera très utile.

J'ajouterais également qu'en déclarant un pointeur vers une classe de base, vous construisez ainsi un "tunnel" vers les descendants à travers la classe de base. Ainsi, le compilateur ne verra que les fonctions déclarées dans la classe de base dans les classes descendantes. Si vous (même dans le même programme) déclarez directement un objet descendant, toutes les fonctions seront disponibles dans celui-ci.

class C_A             //родительский класс
{
 public:
 virtual double function(double a1, double a2, double a3) { return; }
}
class C_B : public C_A
{
 public:
 virtual double function(double a1, double a2, double a3) { return(a1);   }
}
class C_C : public C_A
{
 public:      
 virtual double function(double a1, double a2, double a3) { return(a2);   }
        double function(double a1, double a2)           { return(a1+a2); }
}
//где-то в программе объявляем указатель
C_A  *pointer;
int random=rand()%2;
   switch(random)
     {
      case 0: pointer=new C_B; break;
      case 1: pointer=new C_C; break;
//вызываем виртуальный метод
   if(pointer!=NULL)
     {
      pointer.function(a1,a2,a3);
     }
C_С  *new_pointer=new C_C;
      new_pointer.function(a1,a2);
 
Yedelkin:

Bref, j'ai esquissé cet exemple :

Il s'avère qu'indépendamment du fait qu'une méthode de fonction soit surchargée ou non dans la classe C_C, une fonction virtuelle peut être appelée avec seulement trois paramètres - pointeur.function(a1,a2,a3). Par conséquent, le programme n'atteindra jamais la méthode à deux paramètres de la classe C_C lors de l'appel des fonctions virtuelles. N'est-ce pas ?

D'après ma propre expérience, je peux vous recommander d'emballer le code de la manière suivante

double function(double a1, double a2)            {return(a1+a2);}
double function(double a1, double a2, double a3) {return(a2);}

Et vous pouvez voir le fichier joint à titre d'exemple et de divertissement.

Je ne voulais pas m'embêter avec les pointeurs et les nouveaux, donc j'ai simplement déclaré la classe de travail comme une variable.

Le conseiller expert génère un nombre aléatoire 0/1 à intervalles égaux et, en fonction du résultat, exécute l'une des deux fonctions suivantes : MarketBuy / MarketSell.


Vous pouvez le faire de cette façon si vous voulez

bool MarketBuy(string SymbolTitle,double LotSize,double TP = 0.0,double SL = 0.0);
bool MarketSell(string SymbolTitle,double LotSize,double TP = 0.0,double SL = 0.0);

Mais dans ce cas, un bogue peut se produire à cause du conflit avec

bool MarketBuy(string SymbolTitle,double LotSize);
bool MarketSell(string SymbolTitle,double LotSize);


PS

Je l'ai fait à la main, c'est pourquoi il peut y avoir quelques inexactitudes.

Mais en principe, l'idée de base peut être comprise.

Dossiers :
Forum.mq5  18 kb
 

Merci beaucoup pour ces précieux conseils et orientations ! Je les utiliserai certainement, mais j'aimerais avoir suffisamment de temps pour la théorie et la pratique.

Interesting:

De ma propre expérience, je peux recommander de compléter ainsi le code

double function(double a1, double a2)            {return(a1+a2);}
double function(double a1, double a2, double a3) {return(a2);}
Pourquoi le faire de cette façon ? Quel est le piège ?
 
Yedelkin:

Pourquoi est-ce que c'est comme ça ? Quel est le piège ?

Il y avait un problème avec ça, je crois. Mais je ne me souviens plus lesquelles.

Bref, je m'y suis habitué.

En général, il n'y a pas de différence bien sûr, du moins dans mon exemple, j'ai essayé de permuter les places et tout a fonctionné...

 
Interesting:

Il y avait un problème avec ça, je crois. Mais je ne me souviens plus lesquelles.

OK, en tout cas - je garderai cela à l'esprit.
Raison: