1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
The default behavior of the activation of a member function via a pointer or
i(reference) is that the type of the pointer (or reference) determines the
function that is called. E.g., a tt(Vehicle *) will activate tt(Vehicle)'s
member functions, even when pointing to an object of a derived class. As noted
in this chapter's introduction, this is
referred to as em(early) or
hi(early binding) hi(static binding)
em(static) binding, since the type of function is known
i(compile-time). The em(late) hi(late bining) or hi(dynamic binding)
em(dynamic) binding is achieved in bf(C++) using em(virtual member functions).
A member function becomes a i(virtual member function) when its declaration
starts with the keyword ti(virtual). So once again note that in bf(C++),
different from many other object oriented languages, this is em(not) the
default situation. By default em(static) binding is used.
Once a function is declared tt(virtual) in a i(base class), it remains a
virtual member function in all derived classes; even when the keyword
tt(virtual) is not repeated in a
i(derived class).
As far as the vehicle classification system is concerned (see section
ref(VehicleSystem)) the two member functions tt(weight()) and
tt(setWeight()) might well be declared tt(virtual). The relevant sections of
the class definitions of the class tt(Vehicle) and tt(Truck) are shown
below. Also, we show the implementations of the member functions
tt(weight()) of the two classes:
verb(
class Vehicle
{
public:
virtual int weight() const;
virtual void setWeight(int wt);
};
class Truck: public Vehicle
{
public:
void setWeight(int engine_wt, int trailer_wt);
int weight() const;
};
int Vehicle::weight() const
{
return (weight);
}
int Truck::weight() const
{
return (Auto::weight() + trailer_wt);
}
)
Note that the keyword tt(virtual) em(only) needs to appear in the
tt(Vehicle) base class. There is no need (but there is also no i(penalty)) to
repeat it in derived classes: once tt(virtual), always tt(virtual). On the
other hand, a function may be declared tt(virtual) em(anywhere) in a
i(class hierarchy): the compiler will be perfectly happy if tt(weight())
is declared tt(virtual) in tt(Auto), rather than in tt(Vehicle). The specific
characteristics of virtual member functions would then, for the member
function tt(weight()), only appear with tt(Auto) (and its derived classes)
pointers or references. With a tt(Vehicle) pointer, i(static binding) would
remain to be used. The effect of i(late binding) is illustrated below:
verb(
Vehicle v(1200); // vehicle with weight 1200
Truck t(6000, 115, // truck with cabin weight 6000, speed 115,
"Scania", 15000); // make Scania, trailer weight 15000
Vehicle *vp; // generic vehicle pointer
int main()
{
vp = &v; // see (1) below
cout << vp->weight() << endl;
vp = &t; // see (2) below
cout << vp->weight() << endl;
cout << vp->speed() << endl; // see (3) below
}
)
Since the function tt(weight()) is defined tt(virtual), i(late binding)
is used:
itemization(
it() at (1), tt(Vehicle::weight()) is called.
it() at (2) tt(Truck::weight()) is called.
it() at (3) a syntax error is generated. The member
tt(speed()) is no member of tt(Vehicle), and hence not callable via
a tt(Vehicle*).
)
The example illustrates that hi(callable member functions)
hi(member functions: callable) when a pointer to a class is used
em(only the functions which are members of that class can be called). These
functions em(may) be tt(virtual). However, this only influences the type of
binding (early vs. late) and not the set of member functions that is visible
to the pointer.
A virtual member function cannot be a i(static member function): a virtual
member function is still an ordinary member function in that it has a ti(this)
pointer. As static member functions have no tt(this) pointer, they cannot be
declared virtual.
|