Ordinarily functions are selected at compile time according to the static type of the caller object. e.g.
class X { public: void f(); }; class Y : public X { public: void f(); // identical signature to X's function f }; class Z : public X { public: ... };For these objects:
X x; Y y; Z z;the following calls are valid:
x.f()
calls X's function f,
y.f()
calls Y's function f, and
z.f()
calls X's function f, which Z inherits
When a pointer to type X points to an object of type Y, or of type Z, the static type is still used, according to the sub-type principle, i.e. with
X* px1 = &x; // px1 points to an X X* px2 = &y; // px2 points to a Y X* px3 = &z; // px3 points to a Zthe three calls:
px1->f()
, px2->f()
, and px3->f()
still call X's function f, even though, in the second and third cases, px2 and px3 actually point to
objects of type Y and Z respectively.
This can be altered if the keyword virtual is used on the function declaration in the base class, X:
class X { public: virtual void f(); // needs to be repeated in derived classes };Now, whereas the calls for objects x, y and z remain unchanged, the situation with pointers is different:
px1->f();still calls X's function (the function is not really virtual-- it still has a body!), but
px2->f();now calls Y's function, the function of the object actually pointed to by px2. Also
px3->f();calls X's function, but this time because Z (the type of the object pointed to by px3) inherits it from X.
This selection is done at run-time, and is called dynamic, or late binding.
Copyright © 2003 Roger Hartley