L'overloading di funzioni

Di solito il nome della funzione tende a riflettere il suo scopo principale. Di regola, i programmi leggibili e contengono vari ben selezionati identificatori. Talvolta funzioni diverse vengono utilizzate per gli stessi scopi. Consideriamo, per esempio, una funzione che calcola il valore medio di un array di numeri a doppia precisione e la stessa funzione, ma operante con un array di interi. Entrambi sono comodi da poter essere chiamati AverageFromArray:

//+--------------------------------------------------------------------------------+
//| Il calcolo della media per un array di tipo double                             |
//+--------------------------------------------------------------------------------+
double AverageFromArray(const double & array[],int size)
  {
   if(size<=0) return 0.0;
   double sum=0.0;
   double aver;
//---
   for(int i=0;i<size;i++)
     {
      sum+=array[i];    // Sommatoria per il double
     }
   aver=sum/size;       // Divisione della somma per il numero
//---
   Print("Calcolo della media per un array di tipo double");
   return aver;
  }
//+--------------------------------------------------------------------------------+
/ / | Il calcolo della media per un array di tipo int                              |
//+--------------------------------------------------------------------------------+
double AverageFromArray(const int & array[],int size)
  {
   if(size<=0) return 0.0;
   double aver=0.0;
   int sum=0;
//---
   for(int i=0;i<size;i++)
     {
      sum+=array[i];     // Sommatoria per l'int
     }
   aver=(double)sum/size;// Dare la quantità di tipo double, e dividere
//---
   Print("Calcolo della media per un array di tipo int");
   return aver;
  }

Ogni funzione contiene il messaggio output tramite la funzione Print();

   Print("Calcolo della media per un array di tipo int");

Il compilatore seleziona una funzione necessaria in conformità con i tipi degli argomenti e la loro quantità. La regola, secondo cui la scelta è fatta, è chiamata algoritmo signature matching. Una signature è un elenco dei tipi utilizzati per la dichiarazione della funzione.

Esempio:

//+--------------------------------------------------------------------------------+
//| Funzione di avvio del programma Script                                         |
//+--------------------------------------------------------------------------------+
voidOnStart()
  {
//---
   int    a[5]={1,2,3,4,5};
   double b[5]={1.1,2.2,3.3,4.4,5.5};
   double int_aver=AverageFromArray(a,5);
   double double_aver=AverageFromArray(b,5);
   Print("int_aver = ",int_aver,"   double_aver = ",double_aver);
  }
//--- Risultato dello script
// Calcola la media per un array di tipo int
// Calcola la media per un array di tipo double
// int_aver= 3.00000000    double_aver= 3.30000000

Il function overloading è un processo di creazione di più funzioni con lo stesso nome, ma parametri diversi. Ciò significa che in varianti overload di una funzione, il numero di argomenti e/o i loro tipi devono essere diversi. Una specifica variante di funzione viene selezionata in base alla corrispondenza della lista di argomenti quando si chiama la funzione, per l'elenco dei parametri nella dichiarazione di funzione.

Quando una funzione in overload viene chiamata, il compilatore deve avere un algoritmo per selezionare la funzione appropriata. L'algoritmo che esegue questa scelta dipende dai castings di quali tipi sono presenti. La migliore corrispondenza deve essere univoca. Una funzione overloadata deve essere il miglior connubio tra tutte le altre varianti di almeno un argomento. Allo stesso tempo, deve corrispondere per tutti gli altri argomenti, non peggio di altre varianti.

Di seguito è riportato un algoritmo di corrispondenza per ogni argomento.

Algoritmo di Scelta di una Funzione Overload

  1. Utilizzare la corrispondenza stretta (se possibile).
  2. Prova aumento tipo standard.
  3. Prova typecasting standard.

L'incremento di tipo standard è migliore di altre conversioni standard. Incremento è la conversione di float to double, of bool, char, short or enum to int. Il Typecasting di array di simili tipi integer appartiene anche al typecasting. Tipi simili sono: bool, char, uchar, dal momento che tutti e tre i tipi sono interi a singolo-byte; interi a doppio-byte short ed ushort, interi 4-byte int, uint, e colour; long, ulong e datetime.

Naturalmente, lo strict matching è il migliore. Per ottenere una tale consistenza può essere utilizzato typecasting. Il compilatore non può far fronte a situazioni ambigue. Pertanto non si dovrebbe fare affidamento su sottili differenze di tipi e conversioni implicite che rendono poco chiara la funzione di overload.

Se avete dei dubbi, utilizzare la conversione esplicita per garantire il rispetto rigoroso.

Esempi di funzioni in overloaded in MQL5 si possono vedere nell'esempio di funzioni ArrayInitialize().

Regole di funzioni overloading si applicano a overload dei metodi della classe.

 

L'overloading di funzioni del sistema è consentito, ma va osservato che il compilatore è in grado di selezionare accuratamente la funzione necessaria. Per esempio, siamo in grado di overloadare la funzione di sistema Mathmax() in 4 modi diversi, ma solo due varianti sono corrette.

Esempio:

// 1. overload consentito - la funzione differisce dalla funzione incorporata MathMax() nel numero di parametri
double MathMax(double a,double b,double c);
 
// 2. l'overload non è permesso!
// il umero di parametri è diverso, ma l'ultimo ha un valore predefinito
// questo porta all'occultamento della funzione di sistema quando si chiama, che è inaccettabile
double MathMax(double a,double b,double c=DBL_MIN);
 
// 3. l'overload è consentito - l'overload normale per tipo di parametri a e b
double MathMax(int a,int b);
 
// 4. l'overload non è permesso!
// Il numero ed i tipi di parametri sono gli stessi come nell'originale double MathMax(double a,double b)
int MathMax(double a,double b);

Vedi anche

Overload, Funzioni Virtuali, Polimorfismo