W11-Inheritance and Polymorphism in C++(1)
W11-Inheritance and Polymorphism in C++(1)
3
Inheritance
• Example: Insect Taxonomy
4
Inheritance
• Inheritance is also called an is-a hierarchy
o A poodle is a dog
o A car is a vehicle
o A flower is a plant
o A football player is an athlete
• An object of child class (derived class) is an object of parent
class (base class)
o an UnderGrad is a Student
o a Mammal is an Animal
5
Inheritance
Benefits:
• Code reuse: a derived class can automatically inherit code from
base class
• Polymorphism: Ability to redefine existing behavior but preserve
the interface; children can override the behavior of the parent
• Extensibility: Children can add behavior
class Student // base class
{
. . .
};
7
Class Access Specifiers
• public – object of derived class can be treated as object of
base class (not vice-versa)
• protected – more restrictive than public, but allows
derived classes to know details of parents
• private – prevents objects of derived class from being
treated as objects of base class.
8
Inheritance vs. Access
private members:
When Test class inherits int numQuestions:
from Grade class using float pointsEach;
public class access, it looks like this: int numMissed;
public members:
Test(int, int);
void setScore(float);
float getScore();
char getLetter();
10
Protected Inheritance vs. Access
11
Private Inheritance vs. Access
12
Constructors and Destructors in Inheritance
• A derived class will NOT inherit the constructors, destructor
or assignment operator from a base class
• Derived classes can have their own constructors and
destructors
• When an object of a derived class is created, the base class’s
constructor is executed first, followed by the derived class’s
constructor
• When an object of a derived class is destroyed, its
destructor is called first, then that of the base class
13
Constructors and Destructors in Inheritance
• The execution order of constructors and destructors
#include <iostream>
using namespace std;
class BaseClass {
public:
BaseClass() { cout << "BaseClass Constructor\n"; }
~BaseClass() { cout << "BaseClass Destructor\n"; }
};
14
Constructors and Destructors in Inheritance
Passing arguments to base class constructor
• Allow selection between multiple base class constructors
……
derived constructor base constructor
}
parameters parameter
Base::Base(int v) : value(v) {
Program output: cout<< "value: " << value << endl;
cout << "Base Constructor\n";
value: 10 }
Base Constructor
value: 10 class Derived : public Base {
extraValue: 20 private:
Derived Constructor int extraValue;
public:
Derived(int v1, int v2);
};
int main() {
Derived d1(10, 20);
return 0;
} 16
Constructors and Destructors in Inheritance
• If the base class has no default #include <iostream>
using namespace std;
constructor, then the constructor of class Base {
derived class must pass arguments protected:
int value;
to the parameterized constructor of public:
the base class Base(int v); // Constructor declaration
};
• Otherwise, the compiler does not
know how to initialize the base Base::Base(int v) : value(v) {
cout << "Base Constructor\n";
class, as base class constructor }
must be executed first class Derived : public Base {
private:
int extraValue;
public:
Derived(int v1, int v2);
};
int main() {
Derived d1(10, 20);
return 0;
}
17
Multilevel Inheritance
• A base class can also be derived from another class
18
Multilevel Inheritance
#include <iostream>
using namespace std;
class Vehicle {
public:
Vehicle() { cout << "Vehicle Constructor Called\n"; }
void showVehicle() {
cout << "This is a Vehicle\n";
}
};
class Vehicle {
public:
Vehicle() { cout << "Vehicle Constructor Called\n"; }
~Vehicle() { cout << "Vehicle Destructor Called\n"; }
};
class FourWheeler {
public:
FourWheeler() { cout << "FourWheeler Constructor Called\n"; }
~FourWheeler() { cout << "FourWheeler Destructor Called\n"; }
};
22
Redefining Base Class Functions
#include <iostream>
using namespace std;
class Base {
public:
void display(int a = 10) {
cout<< "Base class display(): " << a << endl;
}
};
int main() {
Base b;
Derived d; Program output:
b.display();
d.display(); Base class display(): 10
return 0; Derived class display(): 100
}
23
Redefining Base Class Functions
– Possible Problem
• Problem: Static Binding -- function calls are bound at the
compile time
#include <iostream>
using namespace std;
class Base {
public:
void display() {
cout<< "Base class display() " << endl;
}
};
class Derived : public Base {
public:
void display() { //It hides Base::display()
cout << "Derived class display() " << endl;
}
}; It will call the
display() function
int main() { in the base class!
Derived d;
d.display();
Program output:
Base* ptr = &d; Derived class display()
ptr->display(); Base class display()
return 0;
}
24
Redefining Base Class Functions
• Redefining vs. overloading
- Overloaded functions have the same function name, but
with a different parameter list
- Overloading can take place inside the same class, i.e.,
multiple member functions of the same class have the same
name
25
Overloading a Base Class Function
#include<iostream>
using namespace std;
class Base {
public:
void show() {
cout << "Base class show()" << endl;
}
};
27
Polymorphism
• Example Recall: Can we use base class pointer to call the function
display() in the derived class?
#include <iostream>
using namespace std;
class Base {
public:
void display() {
cout<< "Base class display() " << endl;
}
};
class Derived : public Base {
public:
void display() { //It hides Base::display()
cout << "Derived class display() " << endl;
}
}; Base Class Pointers
int main() {
Derived d;
- Base class pointers and references only know
d.display(); members of the base classes, so you cannot use
a base class pointer to call a derived class function
Base* ptr = &d; - Redefined functions in the derived class will be
ptr->display();
return 0; ignored unless base class declare the function
} as a virtual function 28
Virtual Functions
• Virtual (member) function: a function in base class that expects
to be redefined in derived class and defined with the keyword
virtual:
virtual void Y() {...}
29
Polymorphism
• An example of using virtual function for runtime polymorphism
#include <iostream>
using namespace std;
class Base {
public:
virtual void display() {
cout<< "Base class display()" << endl;
}
};
class Derived : public Base {
public:
void display() {
cout << “Derived class display()” << endl;
}
};
It will call the
int main() {
Base a; display() function
Derived d; in the derived
a.display(); class now!
d.display();
int main() {
Base a;
Derived d;
a.display();
d.display();
#include <iostream>
using namespace std;
class Base {
public:
virtual void display();
};
void Base::display() { cout<< "Base class display()" << endl; }
32
Polymorphism – Important Notes
• C++ 11 introduces the keyword override in a derived class to explicitly indicate
the purpose of overriding a virtual function in a base class
• The keyword override enhances the code clarity and enables compiler checking
A Coding Mistake
#include <iostream>
using namespace std;
class Base {
public:
virtual void display(int x) {
cout << "Base display: " << x << endl;
}
};
?
int main() {
Derived d; Base display: 42
Base* ptr = &d;
ptr->display(42);
return 0;
}
33
Polymorphism – Important Notes
• C++ 11 introduces the keyword override in a derived class to explicitly indicate
the purpose of overriding a virtual function in a base class
• The keyword override enhances the code clarity and enables compiler checking
A Coding Mistake
#include <iostream>
using namespace std;
class Base {
public:
virtual void display(int x) {
cout << "Base display: " << x << endl;
}
}; With the keyword override, the compiler
can generate error message to remind us
class Derived : public Base { of the code mistake here.
public:
void display(double x) override {
cout << "Derived display: " << x << endl;
}
};
int main() {
Derived d;
Base* ptr = &d;
ptr->display(42);
return 0;
}
34
Virtual Destructor
• You should always declare a destructor virtual, if the class with a
destructor could potentially become a base class
• Reason:
- The compiler will perform static binding on the destructor if
it is not declared virtual
- This can lead to problems when a base class pointer or
reference variable references a derived class object
35
Virtual Destructor
#include <iostream>
using namespace std;
class Animal {
public:
Animal() { cout << "Animal constructor executing.\n"; }
~Animal() { cout << "Animal destructor executing.\n"; }
};
int main() {
Animal* myAnimal = new Dog(); Program output:
delete myAnimal; Animal constructor executing.
myAnimal = nullptr; Dog constructor executing.
return 0; Animal destructor executing.
}
36
Virtual Destructor
#include <iostream>
using namespace std;
class Animal {
public:
Animal() { cout << "Animal constructor executing.\n"; }
virtual ~Animal() { cout << "Animal destructor executing.\n"; }
};
37
Overriding vs. Redefining
• Overriding: a derived class overrides a virtual function of the
base class
-- Overridden functions are dynamically bound
38
Taxonomy of Polymorphism in C++
https://www.geeksforgeeks.org/cpp-polymorphism/ 39
Abstract Base Classes and Pure Virtual
Functions
• Pure virtual function is a virtual member function declared in a
base class like this:
virtual void Y() = 0;
Thank You!