04 Inheritance
04 Inheritance
1
Implement the following class diagram by practicing the concept of
•Inheritance (kind-of)
•Aggregation (has-a)
•Containment (part-whole)
Object Oriented
Programming
Inheritance
2
What is Inheritance ?
Inheritance is the process of creating new classes, called derived classes, from
existing or base classes.
The derived class inherits all the capabilities of the base class but can add more
3
Terminology
Derived class or subclass or child class : A class which inherits some of its
attributes and methods from another class.
Base class or superclass or parent class : A class from which another class
inherits.
Ancestor : A class’s ancestors are those from which its own super classes
inherit.
Descendant : A class’s descendants are those which inherit from its sub classes.
4
Terminology - A Classification Hierarchy
Vehicle
A car is ‘a kind of’ vehicle
car class can inherit from
Car vehicle class
Car
A wheel isn’t ‘a kind of’ car.
A wheel is ‘a part of’ a car
Wheel
7
Designing your classification hierarchy:
Different classes or different states?
Need to analyze whether differences between objects are dependant on type
(such as a house being different to a factory) or state. (different values of the
class’s attributes)
might vary only in the value of
Building the height attribute - don’t need
separate classes
9
Generalization
Sharing commonality between two or more classes
If we were modelling animals in a zoo would we create a separate class for
11
Example: base/Derived Class Constructors (2/3)
class CountDn : public Counter {
public: CountDn() : Counter() {} // constructor, no args
CountDn(int c) : Counter(c) {} // constructor, 1 arg
12
Example 2: Derived Class Constructors
(3/3)
int main() {
CountDn c1;
CountDn c2(100);
c1.set_countDn(20);
c2.set_countDn(200);
13
Generalization
CountDn class inherits all the features of the Counter class. CountDn doesn’t
need a constructor or the get_count() or set_count() functions, because these
already exist in Counter.
The first line of CountDn specifies that it is derived from Counter:
14
Generalization in UML Class Diagrams
In the UML, inheritance is called generalization, because Counter
the parent class is a more general form of the child class. Attributes:
unsigned int count
The child is more specific version of the parent.
Methods:
In figure, the direction of the arrow emphasizes that the Counter()
Counter(int c)
derived class refers to functions and data in the base unsigned int get_count() const
class, while the base class has no access to the derived
class.
CountDn
Attributes:
int start
Methods:
CounterDn()
CounterDn(int c)
void set_count(int s)
int get_count() const
15
CountDn C2; Counter C1;
--C2 ; // OK C1.count = 5;
C2.count = 10; // Error // Error
16
Example 4: Inheritance in the English Distance Class (1/3)
// inheritance using English Distances
#include <iostream>
using namespace std;
enum posneg { pos, neg }; // for sign in DistSign
class Distance { // English Distance class
protected: // NOTE: can’t be private
int feet; float inches;
public:
Distance() : feet(0), inches(0.0) { } // no-arg constructor
Distance(int ft, float in) : feet(ft), inches(in) { }
void getdist() { // get length from user
cout << "\nEnter feet: "; cin >> feet;
cout << "Enter inches: "; cin >> inches;
}
void showdist() const // display distance
{
cout << feet << "\'-" << inches << '\"';
}
};
17
Example 4: Inheritance in the English Distance Class (2/3)
class DistSign : public Distance { // adds sign to Distance
private: posneg sign; // sign is pos or neg
public: // no-arg constructor
DistSign() : Distance() { // call base constructor
sign = pos; // set the sign to +
}
// 2- or 3-arg constructor
DistSign(int ft, float in, posneg sg = pos) : Distance(ft, in) { // call base
constructor
sign = sg; // set the sign
}
void getdist() { // get length from user
Distance::getdist(); // call base getdist()
char ch; // get sign from user
cout << "Enter sign (+ or -): "; cin >> ch;
sign = (ch == '+') ? pos : neg;
}
void showdist() const { // display distance
cout << ((sign == pos) ? "(+)" : "(-)"); // show sign
Distance::showdist(); // ft and in
} 18
};
Example 4: Inheritance in the English Distance Class (3/3)
int main()
{
DistSign alpha; // no-arg constructor
alpha.getdist(); // get alpha from user
DistSign beta(11, 6.25); // 3-arg constructor
DistSign gamma(100, 5.5, neg); // 3-arg constructor
cout << "\nalpha = "; alpha.showdist(); // display all distances
cout << "\nbeta = "; beta.showdist();
cout << "\ngamma = "; gamma.showdist();
cout << endl;
system("PAUSE");
return 0;
}
19
Example 1: Derived Class and Base Class
(1/2)
// inheritance with Counter class
#include <iostream>
using namespace std;
class Counter { // base class
protected: // NOTE: not private
unsigned int count; // count
public:
Counter() : count(0) { } // no-arg constructor
};
20
Example 1: Derived Class and Base Class
(2/2)
class CountDn : public Counter { // derived class
public:
Counter operator -- () { // decr count (prefix)
return Counter(--count);
}
};
int main() {
CountDn c1; // c1 of class CountDn
// CountDn c2(100); // Error
cout << "\nc1=" << c1.get_count(); // display c1
++c1; ++c1; ++c1; // increment c1,3 times
cout << "\nc1=" << c1.get_count(); // display it
--c1; --c1; // decrement c1, twice
cout << "\nc1=" << c1.get_count(); // display it
Counter c; // c of class Counter
// --c; // Error
system("PAUSE");
return 0;
}
21
Example 2: Derived Class Constructors
(1/2)
#include <iostream> // constructors in derived class
using namespace std;
class Counter {
protected: // NOTE: not private
unsigned int count; // count
public:
Counter() : count(0) {} // constructor, no args
Counter(int c) : count(c) {} // constructor, one arg
unsigned int get_count() const { // return count
return count;
}
Counter operator ++ () { // increment count (prefix)
return Counter(++count);
}
};
class CountDn : public Counter {
public: CountDn() : Counter() {} // constructor, no args
CountDn(int c) : Counter(c) {} // constructor, 1 arg
22
Example 2: Derived Class Constructors
(2/2)
CountDn operator -- () { // decr count (prefix)
return CountDn(--count);
}
};
int main() {
CountDn c1; CountDn c2(100);
cout << "\nc1=" << c1.get_count(); // display
cout << "\nc2=" << c2.get_count(); // display
++c1; ++c1; ++c1; // increment c1
cout << "\nc1=" << c1.get_count(); // display it
--c2; --c2; // decrement c2
cout << "\nc2=" << c2.get_count(); // display it
CountDn c3 = --c2; // = calls 1 arg constructor
cout << "\nc3=" << c3.get_count(); // display c3
cout << endl;
system("PAUSE"); return 0;
}
23
Class Hierarchies (UML Diagram)
void getdata()
void putdata() const
25
Example 5: Class Hierarchies ( Employee Database ) (2/4)
class manager : private employee { // management class
private:
char title[LEN]; // "vice-president" etc.
double dues; // golf club dues
public:
void getdata() {
employee::getdata();
cout << " Enter title: "; cin.get(title, LEN);
cout << " Enter golf club dues: "; cin >> dues;
}
26
Example 5: Class Hierarchies ( Employee Database ) (3/4)
class scientist : private employee { // scientist class
{
private:
int pubs; // number of publications
public:
void getdata()
{
employee::getdata();
cout << " Enter number of pubs: "; cin >> pubs;
}
28
“Abstract” Base Class
Notice that we don’t define any objects of the base class employee. We use
this as a general class whose purpose is to act as a base from which other
classes are derived.
The laborer class operates identically to the employee class, since it contains no
class we emphasize that all classes are descended from the same source,
employee.
Also, if in the future we decided to modify the laborer class, we would not need
30
Example 6: Access Combinations (2/2)
class C : private A { // privately-derived class
public:
void funct() {
int a;
a = privdataA; // error: not accessible
a = protdataA; /* OK */ a = pubdataA; // OK
}
};
int main() {
int a; B objB;
a = objB.privdataA; // error: not accessible
a = objB.protdataA; // error: not accessible
a = objB.pubdataA; // OK (A public to B)
C objC;
a = objC.privdataA; // error: not accessible
a = objC.protdataA; // error: not accessible
a = objC.pubdataA; // error: not accessible (A private to
C)
system("PAUSE");
return 0; 31
}
Access Combinations
32
Multi Levels of Inheritance
Media
33
Example 7: Multi Levels of Inheritance (1/4)
// multiple levels of inheritance
#include <iostream>
#include <stdio.h> // for fflush()
using namespace std;
const int LEN = 80;
class employee {
private:
char name[LEN];
unsigned long number;
public:
void getdata() {
cout << "\n Enter last name: ";
cin.get(name, LEN); fflush(stdin);
cout << " Enter number: ";
cin >> number; fflush(stdin);
}
void putdata() const {
cout << "\n Name: " << name;
cout << "\n Number: " << number; UML Diagram
}
}; 34
Example 7: Multi Levels of Inheritance (2/4)
// scientist class
class scientist : public employee {
private:
int pubs; // number of publications
public:
void getdata() {
employee::getdata();
cout << " Enter number of pubs: ";
cin >> pubs;
}
35
Example 7: Multi Levels of Inheritance (3/4)
// laborer class
class laborer : public employee {
};
// foreman class
class foreman : public laborer {
private:
// percent of quotas met successfully
float quotas;
public:
void getdata() {
laborer::getdata();
cout << " Enter quotas: ";
cin >> quotas;
}
void putdata() const {
laborer::putdata();
cout << "\n Quotas: " << quotas;
}
};
36
Example 7: Multi Levels of Inheritance (4/4)
int main() {
laborer l1;
foreman f1;
cout << endl;
cout << "\nEnter data for laborer 1";
l1.getdata();
};
class Printer { // base class Printer
}; Bowler Batsman
38
Multiple Inheritance (UML Diagram)
Person
string name
int age
Person()
void get_data()
void show_data()
Student Faculty
Faculty() void
Teaching Assistant
Teaching Assistant()
void get_all_data()
void show_all_data() 39
Multiple Inheritance (UML Diagram)
Device
string name
Device()
void get_name()
void show_name()
Camera_Phone Teacher
string subject
Teacher()
Camera_Phone() void get_all_data()
void show_all_data() 40
Member Functions in Multiple Inheritance
class student
{ };
class employee
{ };
class manager :
private employee, private student
{ };
class scientist :
private employee, private student
{ };
41
Example 8: Member Functions in Multiple Inheritance (1/5)
//multiple inheritance with employees and degrees
#include <iostream>
using namespace std;
const int LEN = 80; // maximum length of names
class student { // educational background
private:
char school[LEN]; // name of school or university
char degree[LEN]; // highest degree earned
public:
void getedu() {
cout << " Enter name of school or university: ";
cin >> school;
cout << " Enter highest degree earned \n";
cout << " (Highschool, Bachelor's, Master's, PhD): ";
cin >> degree;
}
void putedu() const {
cout << "\n School or university: " << school;
cout << "\n Highest degree earned: " << degree;
}
}; 42
Example 8: Member Functions in Multiple Inheritance (2/5)
class employee
{
private:
char name[LEN]; // employee name
unsigned long number; // employee number
public:
void getdata() {
cout << "\n Enter last name: "; cin >> name;
cout << " Enter number: "; cin >> number;
}
43
Example 8: Member Functions in Multiple Inheritance (3/5)
class manager : private employee, private student {
private:
char title[LEN]; // "vice-president" etc.
double dues; // golf club dues
public:
void getdata() {
employee::getdata();
cout << " Enter title: ";
cin >> title;
cout << " Enter golf club dues: ";
cin >> dues;
student::getedu();
}
void getdata() {
employee::getdata();
cout << " Enter number of pubs: "; cin >> pubs;
student::getedu();
}
};
45
Example 8: Member Functions in Multiple Inheritance (5/5)
class laborer : public employee {
};
int main() {
manager m1; scientist s1, s2; laborer l1;
cout << endl;
cout << "\nEnter data for manager 1"; // get data for
m1.getdata(); // several employees
cout << "\nEnter data for scientist 1"; s1.getdata();
cout << "\nEnter data for scientist 2"; s2.getdata();
cout << "\nEnter data for laborer 1"; l1.getdata();
void getInfo(){
cout << "Enter Employee ID: "; cin >> employeeId;
cout << "Enter Salary: "; cin >> salary;
}
48
Example 9: Constructors in Multiple Inheritance (3/4)
class Teacher : public Person, public Employee {
private:
string subject;
public:
Teacher():Person(), Employee(), subject("") {}
Teacher(const string name, int age, int id, double salary, const string subject)
: Person(name, age), Employee(id, salary), subject(subject) {}
void getInfo(){
Person::getInfo(); Employee::getInfo();
cout << "Enter Subject: ";
std::getline(std::cin >> std::ws, subject); // Read input and ignore leading
whitespaces
}
void showInfo() const {
Person::showInfo(); Employee::showInfo();
cout << "Subject: " << subject << endl;
}
};
49
Example 9: Constructors in Multiple Inheritance (4/4)
int main() {
Teacher t1("M. Ibrahim", 35, 101, 900.0, "Mathematics");
t1.showInfo();
Teacher t2;
t2.getInfo(); Employee
Person
t2.showInfo(); string name int id
Person() Employee()
} void get_data() void get_id()
Teacher
string subject
Teacher()
void get_all_data()
void show_all_data()
50
Ambiguity in Multiple Inheritance: Problem 1
Two base classes have functions with the same name, while a class derived
from both base classes has no function with this name.
How do objects of the derived class access the correct base class function?
The name of the function alone is insufficient, since the compiler can’t figure
51
Example 10: Ambiguity in Multiple Inheritance
#include <iostream> // demonstrates ambiguity in multiple inheritance
using namespace std;
class A {
public: void show() { cout << "Class A\n"; }
};
class B {
public: void show() { cout << "Class B\n"; }
};
int main() {
C objC; // object of class C
// objC.show(); // ambiguous--will not compile
objC.A::show(); // OK
objC.B::show(); // OK
return 0;
}
52
Ambiguity in Multiple Inheritance: Problem 2
Another kind of ambiguity arises if you derive a class from two classes that are
each derived from the same class.
This creates a diamond-shaped inheritance tree.
53
Ex 11: Ambiguity in diamond-shaped multiple inheritance
//diamond.cpp investigates diamond-shaped multiple inheritance
#include <iostream>
using namespace std;
class A {
public:
void func() {
cout << "Hello World \n";
}
};
class B : public A { };
class C : public A { };
class D : public B, public C { };
int main() {
D objD;
// objD.func(); // ambiguous: won’t compile
objD.B::func(); // OK
return 0;
} 54
Aggregation: Classes Within Classes
55
Aggregation: Classes Within Classes
If a class B is derived by inheritance from a class A, we can say that “B is a kind
of A.”
This is because B has all the characteristics of A, and in addition some of its
own.
It’s like saying that a car is a kind of vehicle : A car has the characteristics
shared by all vehicles (wheels, seats, and so on) but has some distinctive
characteristics of its own (CNG, EFI, automatic etc).
For this reason inheritance is often called a “kind of” relationship.
library.
56
Aggregation: Classes Within Classes
Inobject-oriented programming, aggregation may occur when one object is an
attribute of another. Here’s a case where an object of class A is an attribute of
class B:
class A { };
class B { A objA; /* define objA as an object of class A */
};
In the UML, aggregation is considered a special kind of association.
Sometimes it’s hard to tell when an association is also an aggregation.
58
Aggregation: Classes Within Classes
Let’srearrange the EMPMULT program to use aggregation instead of
inheritance.
In EMPMULT the manager and scientist classes are derived from the employee
59
Aggregation: Classes Within Classes
class student { };
class employee { };
class manager {
student stu; // stu is an object of class student
employee emp; // emp is an object of class employee
};
class scientist {
student stu; // stu is an object of class student
employee emp; // emp is an object of class employee
};
class laborer{
employee emp; // emp is an object of class employee
};
61
Example 12: Using Aggregation in the Program (1/6)
// empcont.cpp containership with employees and degrees
#include <iostream>
#include <string>
using namespace std;
class student { // educational background
private:
string school; // name of school or university
string degree; // highest degree earned
public:
void getedu() {
cout << " Enter name of school or university: ";
cin >> school;
cout << " Enter highest degree earned \n";
cout << " (Highschool, Bachelor's, Master's, PhD): ";
cin >> degree;
}
void putedu() const {
cout << "\n School or university: " << school;
cout << "\n Highest degree earned: " << degree;
}
}; 62
Example 12: Using Aggregation in the Program (2/6)
class employee {
private:
string name; // employee name
unsigned long number; // employee number
public:
void getdata() {
cout << "\n Enter last name: ";
cin >> name;
cout << " Enter number: ";
cin >> number;
}
void putdata() const {
cout << "\n Name: " << name;
cout << "\n Number: " << number;
}
};
63
Example 12: Using Aggregation in the Program (3/6)
class manager { // management
private:
string title; // "vice-president" etc.
double dues; // golf club dues
employee emp; // object of class employee
student stu; // object of class student
public:
void getdata() {
emp.getdata();
cout << " Enter title: "; cin >> title;
cout << " Enter golf club dues: "; cin >> dues;
stu.getedu();
}
void putdata() const {
emp.putdata();
cout << "\n Title: " << title;
cout << "\n Golf club dues: " << dues;
stu.putedu();
}
};
64
Example 12: Using Aggregation in the Program (4/6)
class scientist { // scientist
private:
int pubs; // number of publications
employee emp; // object of class employee
student stu; // object of class student
public:
void getdata() {
emp.getdata();
cout << " Enter number of pubs: ";
cin >> pubs;
stu.getedu();
}
void putdata() const {
emp.putdata();
cout << "\n Number of publications: "
<< pubs;
stu.putedu();
}
};
65
Example 12: Using Aggregation in the Program (5/6)
class laborer { // laborer class
private:
employee emp; // object of class employee
public:
void getdata() {
emp.getdata();
}
66
Example 12: Using Aggregation in the Program (6/6)
int main() {
manager m1; scientist s1, s2; laborer l1;
cout << endl;
cout << "\nEnter data for manager 1"; //get data for
m1.getdata(); //several employees
cout << "\nEnter data for scientist 1";
s1.getdata();
cout << "\nEnter data for scientist 2";
s2.getdata();
cout << "\nEnter data for laborer 1"; l1.getdata();
cout << "\nData on manager 1"; // display data for
m1.putdata(); // several employees
cout << "\nData on scientist 1";
s1.putdata();
cout << "\nData on scientist 2";
s2.putdata();
cout << "\nData on laborer 1";
l1.putdata();
cout << endl;
return 0;
} 67
Composition: A Stronger Aggregation
Composition is a stronger form of aggregation. It has all the characteristics of
aggregation, plus two more:
The part may belong to only one whole.
The lifetime of the part is the same as the lifetime of the whole.
A car is composed of doors (among other things). The doors can’t belong to
some other car, and they are born and die along with the car.
A room is composed of a floor, ceiling, and walls.
relationship.
In UML diagrams, composition is shown in the same way as aggregation, except
68
Composition: A Stronger Aggregation
69
Chapter Summary
A class, called the derived class, can inherit the features of another class, called
the base class.
The derived class can add other features of its own, so it becomes a specialized
can be accessed from derived classes but not by any other objects, including
objects of derived classes.
Classes may be publicly or privately derived from base classes. Objects of a
open.
71
Chapter Summary
Inheritance permits the reusability of software: Derived classes can extend the
capabilities of base classes with no need to modify—or even access the source
code of—the base class.
This leads to new flexibility in the software development process, and to a
72
Thank you
73