C++ Concept Map

Virtual functions

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 Z
the 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.


Please mail any corrections and/or suggestions to Roger Hartley at
rth@cs.nmsu.edu

Copyright © 2003 Roger Hartley