OLP. Problemi di applicazione - pagina 4

 
Yedelkin:

Domanda. Una volta che una funzione virtuale con un insieme specifico di parametri e tipi è dichiarata in una classe madre, il numero e i tipi di parametri delle funzioni virtuali corrispondenti possono essere cambiati nelle classi derivate?

Da un lato, il Manuale di Riferimento afferma che "una funzione virtuale può essere sostituita in una classe derivata . Lascelta di quale definizione di funzione chiamare per la funzione virtuale è fatta dinamicamente (a runtime). Un caso tipico è quando una classe base contiene e le classi derivate hanno le proprie versioni di quella funzione". D'altra parte, gli esempi forniti nel Manuale di riferimento si riferiscono a casi in cui le funzioni virtuali hanno corpi di definizione di funzione diversi piuttosto che intestazioni di definizione di funzione.

Per quanto mi ricordi è possibile. Ma bisogna stare assolutamente attenti ai tipi e al numero di parametri.

Bisogna anche fare attenzione ai tipi di valori passati e ai valori predefiniti.

Ecco alcuni esempi per semplicità.

Questa variante farà il trucco.

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

Questo non lo fa (o meglio, forse funzionerà ma con alcuni bug e alcune riserve).

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

Esattamente la stessa cosa accade quando si ricaricano i metodi all'interno di una classe.

 
mql5:
Solo una copia esatta della definizione, ad eccezione delle impostazioni predefinite (le impostazioni predefinite possono variare, ma è meglio non usarla)
Intendi "solo una copia esatta dell'intestazione della definizione"? Dopo tutto, la definizione della funzione include l'intestazione più il corpo. I corpi sono decisamente diversi negli esempi.
 

Interessante, da quanto ho capito, la virtualizzazione delle funzioni e il sovraccarico delle funzioni sono cose leggermente diverse. Emql5 dice che nella virtualizzazione delle funzioni ci dovrebbe essere una copia cartacea dell'intestazione della funzione (non prendo in considerazione i parametri predefiniti).

 
Yedelkin:

Interessante, da quanto ho capito, la virtualizzazione delle funzioni e il sovraccarico delle funzioni sono cose un po' diverse. Emql5 dice che nella virtualizzazione delle funzioni ci dovrebbe essere una copia cartacea dell'intestazione della funzione (non sto prendendo in considerazione i parametri predefiniti).

> Domanda. Dopo la dichiarazione di una funzione virtuale con un certo set di parametri e i loro tipi in una classe madre, è possibile cambiare il numero e i tipi di parametri delle funzioni virtuali corrispondenti nelle classi discendenti?

Se ho capito bene, il figlio deve sovraccaricare la funzionalità dell'antenato.

Francamente parlando, non ricordo di aver fatto queste cose con il virtuale (penso di averlo fatto), ma l'affermazione sul sovraccarico è vera - ho fatto questo errore una volta io stesso.

PS

Se tutto è fatto correttamente, come ho capito, il numero di parametri può essere sia aumentato che diminuito. La difficoltà sarà se il numero di parametri rimane lo stesso, ma i loro tipi sono cambiati...

 

Comunque, ho abbozzato questo esempio:

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);
     }

Si scopre che indipendentemente dal fatto che un metodo di funzione sia sovraccaricato o meno nella classe C_C, una funzione virtuale può essere chiamata con solo tre parametri - pointer.function(a1,a2,a3). Corrispondentemente, il programma non arriverà mai al metodo a due parametri della classe C_C quando chiama le funzioni virtuali. Giusto?

 
Yedelkin:

Comunque, ho abbozzato questo esempio:

Si scopre che indipendentemente dal fatto che un metodo di funzione sia sovraccaricato o meno nella classe C_C, una funzione virtuale può essere chiamata con solo tre parametri - pointer.function(a1,a2,a3). Corrispondentemente, il programma non arriverà mai al metodo a due parametri della classe C_C quando chiama le funzioni virtuali. Giusto?

Analizzare cosa fa il programma inserendo nelle stampe costruttori e distruttori con la macro __FUNCTION__, sarà molto utile.

Aggiungerei anche che dichiarando un puntatore a una classe base, si costruisce così un "tunnel" verso i discendenti attraverso la classe base. Così il compilatore vedrà solo le funzioni dichiarate nella classe base nelle classi discendenti. Se (anche all'interno dello stesso programma) dichiarate direttamente un oggetto discendente, tutte le funzioni saranno disponibili in esso.

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:

Comunque, ho abbozzato questo esempio:

Si scopre che indipendentemente dal fatto che un metodo di funzione sia sovraccaricato o meno nella classe C_C, una funzione virtuale può essere chiamata con solo tre parametri - pointer.function(a1,a2,a3). Corrispondentemente, il programma non arriverà mai al metodo a due parametri della classe C_C quando chiama le funzioni virtuali. Giusto?

Dalla mia esperienza personale posso consigliarvi di impacchettare il codice nel seguente modo

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

E potete vedere il file allegato come esempio e divertimento.

Non volevo preoccuparmi di puntatori e new, quindi ho semplicemente dichiarato la classe di lavoro come una variabile.

L'Expert Advisor genera un numero casuale 0/1 a intervalli uguali e a seconda del risultato esegue una delle due funzioni: MarketBuy / MarketSell.


Puoi farlo in questo modo se vuoi

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);

Ma in questo caso potrebbe verificarsi un bug a causa del conflitto con

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


PS

L'ho fatto a mano, ecco perché ci possono essere delle imprecisioni.

Ma in linea di principio l'idea di base può essere compresa.

File:
Forum.mq5  18 kb
 

Grazie mille per i preziosi consigli e le indicazioni! Li userò sicuramente, ma vorrei avere abbastanza tempo sia per la teoria che per la pratica.

Interesting:

Dalla mia esperienza personale, posso raccomandare di completare così il codice

double function(double a1, double a2)            {return(a1+a2);}
double function(double a1, double a2, double a3) {return(a2);}
Perché farlo in questo modo? Qual è la trappola?
 
Yedelkin:

Perché è così? Qual è la trappola?

Una volta c'era un problema con questo, credo. Ma ora non riesco a ricordare quali.

Comunque, mi sono abituato.

Di solito non c'è differenza, ovviamente, almeno nel mio esempio ho provato a scambiare i posti e tutto ha funzionato...

 
Interesting:

Una volta c'era un problema con questo, credo. Ma ora non riesco a ricordare quali.

OK, in ogni caso - lo terrò a mente.
Motivazione: