Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.11.2b2  El ámbito de nombres y la sobrecarga de métodos

Sinopsis

Se ha indicado ( 4.4.1a) que en C++ no existe el concepto de sobrecarga a través de ámbitos de nombres, y los ámbitos de las clases derivadas no son una excepción a esta regla general. Esto significa que el mecanismo de sobrecarga no funciona para las clases derivadas.

Lo pondremos de manifiesto con un sencillo ejemplo modificando ligeramente el anterior ( 4.11.2b1), de forma que las versiones del método f en la clase-base B y en la derivada D, pudieran ser objeto de sobrecarga:

#include <iostream.h>

class B {               // Superclase
  public: int f(int i) { cout << "Funcion-Superclase "; return i; }
};
class D : public B {    // Subclase
  public: float f(float f) { cout << "Funcion-Subclase "; return f+0.1; }
};

int main() {            // =================
  D d;                  // instancia de subclase
  D* dptr = &d;         // puntero-a-subclase señalando objeto
  B* bptr = dptr;       // puntero-a-superclase señalando objeto de subclase

  cout << "d.f(1)       " << d.f(1) << endl;
  cout << "d.f(1.1)     " << d.f(1.1) << endl;

  cout << "dptr->f(1)   " << dptr->f(1) << endl;
  cout << "dptr->f(1.1) " << dptr->f(1.1) << endl;

  cout << "bptr->f(1)   " << bptr->f(1) << endl;
  cout << "bptr->f(1.1) " << bptr->f(1.1) << endl;
}

Salida:

d.f(1)       Funcion-Subclase 1.1
d.f(1.1)     Funcion-Subclase 1.2
dptr->f(1)   Funcion-Subclase 1.1
dptr->f(1.1) Funcion-Subclase 1.2
bptr->f(1)   Funcion-Superclase 1
bptr->f(1.1) Funcion-Superclase 1

Comentario

Comprobamos que cualquiera que sea la forma de invocación utilizada, en ningún caso se produce sobrecarga de la función; siempre se accede a la misma versión, dependiendo del subespacio de nombres B o D referenciado.

Nota:  si el mecanismo de sobrecarga de funciones hubiese funcionado entre los subespacios de nombres del objeto d, las salidas habrían sido:

d.f(1)       Funcion-Superclase 1
d.f(1.1)     Funcion-Subclase 1.2
dptr->f(1)   Funcion-Superclase 1
dptr->f(1.1) Funcion-Subclase 1.2
bptr->f(1)   Funcion-Superclase 1
bptr->f(1.1) Funcion-Subclase 1.2


En estas condiciones cabe preguntarse ¿Que podríamos hacer si realmente necesitamos el funcionamiento del mecanismo de sobrecarga?. Es decir, si deseamos que, en concordancia con los argumentos de llamada, sea invocada la versión de f definida en la subclase o de la superclase.

La solución está en utilizar la declaración using ( 4.1.11c). Veámoslo mediante un ejemplo modificando ligeramente el caso anterior (para simplificar el código se han disminuido las salidas).

#include <iostream.h>

class B {                // Superclase
  public: int f(int i) { cout << "Funcion-Superclase "; return i; }
};
class D : public B {     // Subclase
  public:

  using B::f;            // Ok. acceder a las versiones de f en B

  float f(float f) { cout << "Funcion-Subclase "; return f+0.1; }
};

int main() {             // =================
  D d;
  D* dptr = &d;
  B* bptr = dptr;

  cout << dptr->f(1) << endl;
  cout << dptr->f(1.0) << endl;
  cout << bptr->f(1) << endl;
  cout << bptr->f(1.0) << endl;
}

Salida [1]:

Funcion-Superclase 1
Funcion-Subclase 1.1
Funcion-Superclase 1
Funcion-Superclase 1

Comentario

En este caso comprobamos como la sobrecarga ha funcionado en el sentido D B. Cuando accedemos al espacio de nombres D, se invoca correctamente la versión adecuada de f, pero cuando accedemos a B, el espacio D sigue siendo invisible para el mecanismo de sobrecarga.

La representación gráfica idealizada de la situación para la clase derivada D sería la siguiente:

namespace D {

   using B::f;

   float f(float f);

   namespace B {

      int f(inf i);

   }

}

Cuando se utiliza un identificador como d.f(), o su equivalente dptr->f(), se accede directamente al subespacio D, aunque las versiones interiores de f son accesibles por la declaración using; pero cuando se accede directamente al subespacio B mediante expresiones como bptr->f(), la versión de f en este subespacio sigue ocultando cualquier otro identificador exterior.

Ver otro ejemplo en: "Acceso a subespacios en clases" ( 4.1.11c1)

  Inicio.


[1]  Aunque los comportamientos descritos en el ejemplo son los Estándar, el compilador Borland C++ 5.5 para Win-32 presenta un error, por lo que los resultados se han obtenido con el compilador MS Visual C++ 6.0 que en este punto se acerca más a la norma.