Sobrecarga de funciones

Por lo común, en el nombre de una función intentan reflejar su principal finalidad. Por regla general, los programas legibles contienen diversos identificadores bien seleccionados. A veces, diferentes funciones se usan con los mismos propósitos. Vamos a considerar, por ejemplo, la función que calcula el valor promedio del array de números de doble precisión, y la misma función pero la que opera con el array de números enteros. Es cómodo nombrar ambas funciones AverageFromArray:

//+------------------------------------------------------------------+
//| cálculo del promedio para el array de 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];    // suma para double
     }
   aver=sum/size;       // simplemente dividimos la suma por la cantidad
//---
   Print("Cálculo de la media para un array del tipo double");
   return aver;
  }
//+------------------------------------------------------------------+
//| cálculo del promedio para el array de 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];     // suma para int
     }
   aver=(double)sum/size;// convertimos la suma al tipo double y la dividimos
//---
   Print("Cálculo de la media para un array del tipo int");
   return aver;
  }

Cada función contiene la extracción del mensaje a través de la función Print();

   Print("Cálculo de la media para un array del tipo int");

El compilador elige una función necesaria de acuerdo con los tipos de argumentos y su cantidad. La regla, según la cual se hace la elección, se llama algoritmo de equivalencia a la signatura. Una signatura es una lista de tipos usados en la declaración de función.

Ejemplo:

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   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);
  }
//--- Resultado de funcionamiento del script
// cálculo del promedio para el array de tipo int
// cálculo del promedio para el array de tipo double
// int_aver = 3.00000000    double_aver = 3.30000000

La sobrecarga es la práctica de asignación de varios valores a una función. La elección de un valor específico depende de los tipos de argumentos recibidos por la función. Una función específica se elige a base de la correspondencia de la lista de argumentos durante la invocación de la función a la lista de parámetros en la declaración de la función.

Cuando se invoca una función sobrecargada, el compilador debe tener un algoritmo para elegir una función apropiada. El algoritmo que hace la elección depende del tipo de conversiones que estén presentes. La mejor correlación tiene que ser única. Tiene que ser la mejor por lo menos para uno de los argumentos, e igual de buena como las demás correspondencias para todos los otros argumentos.

Más abajo viene el algoritmo de correspondencia para cada argumento.

Algoritmo de elección de una función sobrecargada

  1. Usar la correspondencia estricta (si es posible).
  2. Intentar el incremento estándar del tipo.
  3. Intentar la transformación estándar del tipo.

El incremento estándar del tipo es mejor que las demás transformaciones estándar. El incremento es una transformación float en double, y también bool, char, short o enum en int. Además, a las transformaciones estándar pertenecen las transformaciones de los arrays de tipos enterossimilares. Los tipos similares son los siguientes: bool, char, uchar, puesto que estos tres tipos son enteros de un byte; los enteros de dos bytes short y ushort; los enteros de 4 bytes int, uint y color; long, ulong y datetime.

No hay duda que la correspondencia estricta es la mejor. Para conseguirla se puede usar las coversiones. El compilador no podrá con una situación de doble sentido, así que no hay que fiarse de las ligeras diferencias en los tipos y las transformaciones implícitas que hacen la función sobrecargada poco clara.

Si Usted tiene duda, recurra a las conversiones explícitas para conseguir la correspondencia estricta.

Como ejemplo de las funciones sobrecargadas en MQL5 puede servir el de la función ArrayInitialize().

Las reglas de sobrecarga de funciones también se aplican a la sobrecarga de métodos de clases.

 

La sobrecarga de las funciones del sistema está permitida pero en este caso hay que mirar que el compilador pueda elegir sin problema alguno la función necesaria. Como ejemplo, podemos sobrecargar la función del sistema fmax() de 3 formas distintas, pero sólo dos opciones van a ser correctas.

Ejemplo:

// sobrecarga está permitida - se diferencia por la cantidad de parámetros
double fmax(double a,double b,double c);
 
// sobrecarga con error
// la cantidad de parámetros es diferente, pero el último tiene el valor por defecto
// eso lleva a la ocultación de la función del sistema durante la llamada, pero esto es inaceptable
double fmax(double a,double b,double c=DBL_MIN);
 
// sobrecarga normal por el tipo de parámetro
int fmax(int a,int b);

Véase también

Sobrecarga, Funciones virtuales, Polimorfismo