What is an example of run time polymorphism in c plus plus?
Consult the following program. Three classes are declared, A, B
and C, such that B and C both inherit from A. Thus B and C are said
to be a "kind of" A. Class A includes a virtual method named
action() which is overridden by both B and C. Thus B and C are more
specialised than A. All the methods simply print stubs to show
which method has been executed.
The main function instantiates one instance of each class and
passes all three to the nonpolymorph() function before passing them
to the polymorph() function. Both functions accept a reference to
an A object and both functions invoke the action() method for that
object. Both functions execute the correct method regardless of
which type of object is passed.
The nonpolymorphic() function is the least efficient method of
enabling runtime polymorphism because the function itself needs to
know the exact type of the object being passed in order to invoke
the correct method. In this case it examines the last character of
the runtime type name and switches accordingly. With more complex
class names you might be forced to use nested ifs to compare names,
which is even more costly in terms of performance. Once the correct
class is determined, a dynamic cast is used for B and C objects to
invoke the correct method.
Note that if you should happen to derive new classes from A, you
must also update this function to cater for them (adding new
cases). In a real program you might have dozens of functions like
this and each must be updated accordingly to cater for all new
types. This can very quickly become a maintenance nightmare.
The polymorph() function, on the other hand, is not only simpler
to implement it requires no additional maintenance whatsoever. It
will cater for any class that inherits from A both now and in the
future. It is able to achieve runtime polymorphism by virtue of the
fact the A class has a virtual function which both B and C
override. When you declare a virtual function, you create a virtual
table for that class as well as all those that derive from it (that
is, one table per class, not one table per object of the class).
This consumes a little bit more memory than normal, but the table
is simply an array of virtual function pointers that point to the
appropriate overrides for that particular class. So the A class
table entry will point to A::action(), while the B class table
entry will point to B::action(), and so on. Thus you get the
expected behaviour without the need for expensive runtime
information.
Virtual methods mimic the way objects work in real life to some
extent. For instance, imagine the function is you and A, B and C
are black box objects that can make a sound at the press of a
button on top of the box. Someone places one of these objects in
front of you and, although you have no idea what type of object it
is, you know you can simply press the button and it will make a
sound. In other words you know how the interface works, the object
itself decides how that interface is implemented. If the button
were not on top of the box then you might have to feel around the
box to locate the button. This is akin to using runtime type
information to get the additional information you need to use the
interface. Sometimes this is required but it is usually a sign of
poor design. When interfaces are consistent, then your need to know
the type of object is wholly irrelevant.
#include<iostream>
#include<typeinfo>
using namespace std;
struct A
{
virtual void action () { cout << "A::action()\n" <<
endl; }
};
struct B : A
{
void action () override { cout << "B::action()\n" <<
endl; }
};
struct C: A
{
void action () override { cout << "C::action()\n" <<
endl; }
};
void nonpolymorph(A& a)
{
std::string s (typeid(a).name());
switch (s.at( s.size()-1))
{
case ('A'): a.action(); break;
case ('B'): (dynamic_cast<B&>(a)).action(); break;
case ('C'): (dynamic_cast<C&>(a)).action(); break;
}
}
void polymorph(A& a)
{
a.action();
}
int main()
{
A a;
B b;
C c;
nonpolymorph (a);
nonpolymorph (b);
nonpolymorph (c);
polymorph (a);
polymorph (b);
polymorph (c);
}