15.5.5. Los objetos son diferentes

Es importante darse cuenta de que el upcasting sólo maneja direcciones. Si el compilador tiene un objeto, sabe su tipo concreto y además (en C++) no se usará la ligadura dinámica para ninguna de las llamadas a funciones - o como mínimo el compilador no necesitará usar la ligadura dinámica. Por cuestiones de eficiencia, la mayoría de los compiladores usarán la ligadura estática cuando esten haciendo una llamada a una función virtual de un objeto porque saben su tipo concreto. Aquí hay un ejemplo:

//: C15:Early.cpp
// Early binding & virtual functions
#include <iostream>
#include <string>
using namespace std;

class Pet {
public:
  virtual string speak() const { return ""; }
};

class Dog : public Pet {
public:
  string speak() const { return "Bark!"; }
};

int main() {
  Dog ralph;
  Pet* p1 = &ralph;
  Pet& p2 = ralph;
  Pet p3;
  // Late binding for both:
  cout << "p1->speak() = " << p1->speak() <<endl;
  cout << "p2.speak() = " << p2.speak() << endl;
  // Early binding (probably):
  cout << "p3.speak() = " << p3.speak() << endl;
} ///:~

Listado 15.5. C15/Early.cpp


En p1->speak() y en p2.speak(), se usan direcciones, lo que significa que la información es incompleta: p1 y p2 pueden representar la dirección de una Pet o algo que derivee de una Pet, por lo que el debe ser usado el mecanismo virtual. Cuando se llama a p3.speak no existe ambigüedad. El compilador conoce el tipo exacto del objeto, lo que hace imposible que sea un objeto derivado de Pet - es exactamente una Pet. Por esto, probablemente se use la ligadura estática. Sin embargo, si el compilador no quiere trabajar mucho, puede usar la ligadura dinámica y el comportamiento será el mismo.