15.2. Upcasting

En el Capítulo 14 se vio cómo un objeto puede ser usado como un objeto de su propio tipo o como un objeto de su tipo base. Además el objeto puede ser manejado a través de una dirección del tipo base. Tomar la dirección de un objeto (ya sea un puntero o una referencia) y tratarlo como la dirección de su tipo base se conoce como upcasting [78] debido a la forma en que se dibujan los árboles de herencia, con la clase base en la parte superior.

También se vio surgir un problema, que se plasma en el siguiente código:

//: C15:Instrument2.cpp
// Inheritance & upcasting
#include <iostream>
using namespace std;
enum note { middleC, Csharp, Eflat }; // Etc.

class Instrument {
public:
  void play(note) const {
    cout << "Instrument::play" << endl;
  }
};

// Wind objects are Instruments
// because they have the same interface:
class Wind : public Instrument {
public:
  // Redefine interface function:
  void play(note) const {
    cout << "Wind::play" << endl;
  }
};

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

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

Listado 15.1. C15/Instrument2.cpp


La función tune() acepta (por referencia) un Instrument, pero también acepta sin quejarse cualquier cosa que derive de Instrument. En el main(), se puede ver este comportamiento cuando se pasa un objeto Wind a tune() sin que se necesite ningún molde. Esto es aceptable; la interfaz de Instrument tiene que existir en Wind, porque Wind hereda públicamente de Instrument. El upcasting de Wind a Instrument puede «estrechar» esa interfaz, pero nunca por debajo de la interfaz completa de Instrument.

Los mismos argumentos son válidos cuando se trabaja con punteros; la única diferencia es que el usuario debe tomar la dirección de los objetos de forma explícita cuando se pasan a la función.



[78] N del T: Por desgracia upcasting es otro de los términos a los que no he encontrado una traducción convincente (¿¿amoldar hacia arriba??) y tiene el agravante de que deriva de una expresión ampliamente usada por los programadores de C (¿Quién no ha hecho nunca un cast a void* ;-) ?. Se aceptan sugerencias.