Virtual functions
-- dispatching
class A { \fbox{A}
public:
virtual void operator()() {
cout << "A";
}
};
class B : public A { \fbox{B}
public:
virtual void operator()() {
cout << "B";
}
};
\nop{
Usage
}
}{
Virtual functions
-- dispatching
class A { \fbox{A}
public:
virtual void operator()() { cout << "A"; }
};
class B : public A { \fbox{B}
public:
virtual void operator()() { cout << "B"; }
};
\nop{
Usage
}
}
}
\c{
The class A defines a virtual member function
(that results in printing A) which is redefined
by a similar function in class B (which results
in printing B).
As an example of using the classes defined above
look at the following program fragment.
A* a = new B(); (*a)();
In case the function would not have been defined as virtual,
the outcome of applying it to (a pointer to) a B object
would have been A, instead of B.
}
\c{
Virtual functions that are redefined in derived classes
may still access the original version defined in the base
class, as illustated in slide [7-scoping].
}
\slide{7-scoping}{Virtual functions -- scoping}{
Scoping
-- explicit
class B : public A { \fbox{}
public:
virtual void operator()() {
cout << "B";
A::operator()();
}
};
}{
Scoping
-- explicit
class B : public A { \fbox{}
public:
virtual void operator()() {
cout << "B"; A::operator()();
}
};
}
}
\c{
Scoping may be used within a member function of the
class as well as by a client (when invoking a member
function) as illustrated below.
A* a = new B(); a->A::operator()(); (*a)();
The outcome of this statement is ABA.
Such a scoping mechanism is certainly not unique
to C++, although the notation for it is.
In Smalltalk, the expression super may be used
to access methods defined in the ancestor class,
and in Eiffel one must use a combination of
redefining and renaming to achieve this.
As a remark, occasionally I prefer the use of
when any other method name would
be arbitrary.
The attractiveness of is
that it is used as a function application
operator, as in $(*a)()