[ fromfile: inheritance-intro.xml id: polymorphism ]
We now introduce another powerful feature of object-oriented programming: polymorphism.
Example 6.6 differs from the previous example in only one important way: the use of the keyword virtual
in the base class definition.
Example 6.6. src/derivation/qpoly/student.h
[ . . . . ] class Student { public: Student(QString nm, long id, QString major, int year = 1); virtual ~Student() {} virtual QString getClassName() const; QString toString() const; private: QString m_Name; QString m_Major; long m_StudentId; protected: int m_Year; QString yearStr() const; };
<include href="src/derivation/qpoly/student.h" segid="student" src="src/derivation/qpoly/student.h" mode="cpp" id="src-polystu"/>
Adding the keyword virtual
to at least one member function creates a polymorphic type.
virtual
functions are called methods.
This terminology is consistent with the use of that term in Java, where member functions are "methods" by default.
Example 6.7 shows the same client code again.
Example 6.7. src/derivation/qpoly/student-test.cpp
#include <QTextStream> #include "student.h" static QTextStream cout(stdout); void finish(Student* student) { cout << "\nThe following " << student->getClassName() << " has applied for graduation.\n " << student->toString() << "\n"; } int main() { Undergrad us("Frodo Baggins", 5562, "Ring Theory", 4, 1220); GradStudent gs("Bilbo Baggins", 3029, "History", 6, GradStudent::fellowship); cout << "Here is the data for the two students:\n"; cout << gs.toString() << endl; cout << us.toString() << endl; cout << "\nHere is what happens when they finish their studies:\n"; finish(&us); finish(&gs); return 0; }
<include src="src/derivation/qpoly/student-test.cpp" href="src/derivation/qpoly/student-test.cpp" id="src-polyclient" mode="cpp"/>
When you run this slightly changed program you get the following output.
Here is the data for the two students: [GradStudent] name: Bilbo Baggins; Id: 3029; Year: gradual student; Major: History [Support: fellowship ] [Undergrad] name: Frodo Baggins; Id: 5562; Year: senior; Major: Ring Theory [SAT: 1220 ] Here is what happens when they finish their studies: The following Undergrad has applied for graduation. [Undergrad] name: Frodo Baggins; Id: 5562; Year: senior; Major: Ring Theory [46] The following GradStudent has applied for graduation. [GradStudent] name: Bilbo Baggins; Id: 3029; Year: gradual student; Major: History[47]
[GradStudent]
and [UnderGrad]
now appear in the output, because getClassName()
is virtual
.
There is still a problem with the output of finish()
for the GradStudent
, however. The Support
piece is missing.
With polymorphism, indirect calls (via pointers and references) to methods are resolved at runtime. This is called dynamic, or runtime binding. Direct calls (not through pointers or references) of methods are resolved by the compiler. That is called static binding or compile time binding.
In this example, when finish()
receives the address of a GradStudent
object, student->toString()
calls the Student
version of the function.
However, when the Student::toString()
calls getClassName()
(indirectly through this
, a base class pointer), it is a virtual
method call, bound at runtime.
In C++, dynamic binding is an option that one must switch on with the keyword virtual
.
Virtual calls from Constructors | |
---|---|
Because " |
Virtual Destructors | |
---|---|
In general, if a class has one or more |
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |