14.10. Upcasting

Anteriormente en este capitulo, observo como un objeto de una clase que derivaba de ifstream tenia todas las características y conductas de un objeto ifstream. En FName2.cpp, cualquier función miembro de ifstream podría ser llamada por cualquier objeto FName2.

El aspecto más importante de la herencia no es proporcionar nuevas funciones miembro a la nueva clase. Es la relación expresada entre la nueva clase y la clase base. Esta relación puede ser resumida diciendo "La nueva clase es de un tipo de una clase existente".

Esta no es una descripción fantasiosa de explicar la herencia - esta directamente soportada por el compilador. Un ejemplo, considere una clase base llamada Instrument que representa instrumentos musicales y una clase derivada llamada Wind. Dado que la herencia significa que todas las funciones en la clase base están también disponibles en la clase derivada, cualquier mensaje que envié a la clase base puede ser también enviado desde la derivada. Entonces si la clase Instrument tiene una función miembro play(), también existirá en los instrumentos de Wind. Esto significa precisamente que un objeto Wind es un tipo de Instrument. El siguiente ejemplo muestra como el compilador soporta esta idea:

//: C14:Instrument.cpp
// Inheritance & upcasting
enum note { middleC, Csharp, Cflat }; // Etc.

class Instrument {
public:
  void play(note) const {}
};

// Wind objects are Instruments
// because they have the same interface:
class Wind : public Instrument {};

void tune(Instrument& i) {
  // ...
  i.play(middleC);
}

int main() {
  Wind flute;
  tune(flute); // Upcasting
} ///:~

Listado 14.17. C14/Instrument.cpp


Lo interesante en este ejemplo es la función tune(), que acepta una referencia Instrument. Sin embargo, en main() la función tune() se llama utilizando una referencia a un objeto Wind. Dado que C++ es un muy peculiar sobre la comprobación de tipos, parece extraño que una función que acepta solo un tipo pueda aceptar otro tipo, al menos que sepa que un objeto Instrument es tambien un objeto Instrument.

14.10.1. ¿Por qué «upcasting»?

La razón de este término es histórica y esta basada en la manera en que se dibuja la herencia: con la raíz en la parte superior de la pagina y hacia abajo (por supuesto que puede pintar su diagrama de cualquier modo que le sea útil). El diagrama para Instrument.cpp es:

Upcasting

Figura 14.1. Upcasting


El hecho de pasar de la clase derivada a la clase base, esto es, desplazarse hacia arriba en el diagrama de la herencia, es normalmente conocido como upcasting. Upcasting es siempre seguro porque se esta desplazando de un tipo desde un tipo mas especifico a otro tipo mas general. - únicamente puede ocurrir es que la interfaz de la clase pierda algunas funciones miembro, pero no ganarlas. Esto es porque el compilador permite el upcasting sin ninguna conversión explicita o notación especial.