Polymorphism - C++ Tutorials
Polymorphism - C++ Tutorials
Search: Go
Not logged in
C++
Information
Tutorials
A conference about innovations in learning, to OPEN
Reference
Articles
be held online, June 14-18
Forum
Tutorials Polymorphism
C++ Language Before getting any deeper into this chapter, you should have a proper understanding of pointers and class inheritance.
Ascii Codes If you are not really sure of the meaning of any of the following expressions, you should review the indicated sections:
Boolean Operations
Numerical Bases Statement: Explained in:
C++ Language int A::b(int c) { } Classes
Introduction:
a->b Data structures
Compilers class A: public B {}; Friendship and inheritance
Basics of C++:
Structure of a program
Variables and types Pointers to base class
Constants One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its
Operators base class. Polymorphism is the art of taking advantage of this simple but powerful and versatile feature.
Basic Input/Output
Program structure: The example about the rectangle and triangle classes can be rewritten using pointers taking this feature into account:
Statements and flow control
Functions 1 // pointers to base class 20
Overloads and templates 2 #include <iostream> 10
Name visibility
3 using namespace std;
4
Compound data types:
5 class Polygon {
Arrays 6 protected:
Character sequences 7 int width, height;
Pointers 8 public:
Dynamic memory 9 void set_values (int a, int b)
Data structures 10 { width=a; height=b; }
11 };
Other data types
12
Classes:
13 class Rectangle: public Polygon {
Classes (I) 14 public:
Classes (II) 15 int area()
Special members 16 { return width*height; }
Friendship and inheritance 17 };
18 Edit
Polymorphism
19 class Triangle: public Polygon { &
Other language features: Run
20 public:
Type conversions
21 int area()
Exceptions 22 { return width*height/2; }
Preprocessor directives 23 };
Standard library: 24
Input/output with files 25 int main () {
26 Rectangle rect;
27 Triangle trgl;
28 Polygon * ppoly1 = ▭
29 Polygon * ppoly2 = &trgl;
30 ppoly1->set_values (4,5);
31 ppoly2->set_values (4,5);
32 cout << rect.area() << '\n';
33 cout << trgl.area() << '\n';
34 return 0;
35 }
Function main declares two pointers to Polygon (named ppoly1 and ppoly2). These are assigned the addresses of rect
and trgl, respectively, which are objects of type Rectangle and Triangle. Such assignments are valid, since both
Rectangle and Triangle are classes derived from Polygon.
Dereferencing ppoly1 and ppoly2 (with ppoly1-> and ppoly2->) is valid and allows us to access the members of their
pointed objects. For example, the following two statements would be equivalent in the previous example:
1 ppoly1->set_values (4,5);
2 rect.set_values (4,5);
But because the type of both ppoly1 and ppoly2 is pointer to Polygon (and not pointer to Rectangle nor pointer to
Triangle), only the members inherited from Polygon can be accessed, and not those of the derived classes Rectangle
and Triangle. That is why the program above accesses the area members of both objects using rect and trgl directly,
instead of the pointers; the pointers to the base class cannot access the area members.
Member area could have been accessed with the pointers to Polygon if area were a member of Polygon instead of a
member of its derived classes, but the problem is that Rectangle and Triangle implement different versions of area,
therefore there is not a single common version that could be implemented in the base class.
Virtual members
A virtual member is a member function that can be redefined in a derived class, while preserving its calling properties
through references. The syntax for a function to become virtual is to precede its declaration with the virtual keyword:
1 // virtual members 20
2 #include <iostream> 10 Edit
3 using namespace std; 0
4
https://www.cplusplus.com/doc/tutorial/polymorphism/ 1/4
6/3/2021 Polymorphism - C++ Tutorials
5 class Polygon { &
6 protected: Run
7 int width, height;
8 public:
9 void set_values (int a, int b)
10 { width=a; height=b; }
11 virtual int area ()
12 { return 0; }
13 };
14
15 class Rectangle: public Polygon {
16 public:
17 int area ()
18 { return width * height; }
19 };
20
21 class Triangle: public Polygon {
22 public:
23 int area ()
24 { return (width * height / 2); }
25 };
26
27 int main () {
28 Rectangle rect;
29 Triangle trgl;
30 Polygon poly;
31 Polygon * ppoly1 = ▭
32 Polygon * ppoly2 = &trgl;
33 Polygon * ppoly3 = &poly;
34 ppoly1->set_values (4,5);
35 ppoly2->set_values (4,5);
36 ppoly3->set_values (4,5);
37 cout << ppoly1->area() << '\n';
38 cout << ppoly2->area() << '\n';
39 cout << ppoly3->area() << '\n';
40 return 0;
41 }
In this example, all three classes (Polygon, Rectangle and Triangle) have the same members: width, height, and
functions set_values and area.
The member function area has been declared as virtual in the base class because it is later redefined in each of the
derived classes. Non-virtual members can also be redefined in derived classes, but non-virtual members of derived
classes cannot be accessed through a reference of the base class: i.e., if virtual is removed from the declaration of
area in the example above, all three calls to area would return zero, because in all cases, the version of the base class
would have been called instead.
Therefore, essentially, what the virtual keyword does is to allow a member of a derived class with the same name as
one in the base class to be appropriately called from a pointer, and more precisely when the type of the pointer is a
pointer to the base class that is pointing to an object of the derived class, as in the above example.
Note that despite of the virtuality of one of its members, Polygon was a regular class, of which even an object was
instantiated (poly), with its own definition of member area that always returns 0.
Notice that area has no definition; this has been replaced by =0, which makes it a pure virtual function. Classes that
contain at least one pure virtual function are known as abstract base classes.
Abstract base classes cannot be used to instantiate objects. Therefore, this last abstract base class version of Polygon
could not be used to declare objects like:
But an abstract base class is not totally useless. It can be used to create pointers to it, and take advantage of all its
polymorphic abilities. For example, the following pointer declarations would be valid:
1 Polygon * ppoly1;
2 Polygon * ppoly2;
And can actually be dereferenced when pointing to objects of derived (non-abstract) classes. Here is the entire
example:
https://www.cplusplus.com/doc/tutorial/polymorphism/ 2/4
6/3/2021 Polymorphism - C++ Tutorials
2 // abstract base class 20
3 #include <iostream> 10 Edit
4 using namespace std; &
5 Run
6 class Polygon {
7 protected:
8 int width, height;
9 public:
10 void set_values (int a, int b)
11 { width=a; height=b; }
12 virtual int area (void) =0;
13 };
14
15 class Rectangle: public Polygon {
16 public:
17 int area (void)
18 { return (width * height); }
19 };
20
21 class Triangle: public Polygon {
22 public:
23 int area (void)
24 { return (width * height / 2); }
25 };
26
27 int main () {
28 Rectangle rect;
29 Triangle trgl;
30 Polygon * ppoly1 = ▭
31 Polygon * ppoly2 = &trgl;
32 ppoly1->set_values (4,5);
33 ppoly2->set_values (4,5);
34 cout << ppoly1->area() << '\n';
35 cout << ppoly2->area() << '\n';
36 return 0;
}
In this example, objects of different but related types are referred to using a unique type of pointer (Polygon*) and the
proper member function is called every time, just because they are virtual. This can be really useful in some
circumstances. For example, it is even possible for a member of the abstract base class Polygon to use the special
pointer this to access the proper virtual members, even though Polygon itself has no implementation for this function:
Virtual members and abstract classes grant C++ polymorphic characteristics, most useful for object-oriented projects.
Of course, the examples above are very simple use cases, but these features can be applied to arrays of objects or
dynamically allocated objects.
Here is an example that combines some of the features in the latest chapters, such as dynamic memory, constructor
initializers and polymorphism:
https://www.cplusplus.com/doc/tutorial/polymorphism/ 3/4
6/3/2021 Polymorphism - C++ Tutorials
9 Polygon (int a, int b) : width(a), height(b) {}
10 virtual int area (void) =0;
11 void printarea()
12 { cout << this->area() << '\n'; }
13 };
14
15 class Rectangle: public Polygon {
16 public:
17 Rectangle(int a,int b) : Polygon(a,b) {}
18 int area()
19 { return width*height; }
20 };
21
22 class Triangle: public Polygon {
23 public:
24 Triangle(int a,int b) : Polygon(a,b) {}
25 int area()
26 { return width*height/2; }
27 };
28
29 int main () {
30 Polygon * ppoly1 = new Rectangle (4,5);
31 Polygon * ppoly2 = new Triangle (4,5);
32 ppoly1->printarea();
33 ppoly2->printarea();
34 delete ppoly1;
35 delete ppoly2;
36 return 0;
37 }
are declared being of type "pointer to Polygon", but the objects allocated have been declared having the derived class
type directly (Rectangle and Triangle).
Previous: Next:
Friendship and inheritance Type conversions
Index
https://www.cplusplus.com/doc/tutorial/polymorphism/ 4/4