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.