You are on page 1of 37

Composition

Composition (also called containment or aggregation)


refers to the use of one or more classes within the
definition of another class.
Composition is called a has-a relationship. For
example, a car has a steering wheel.
Composition may occur when one object is an attribute
of another object.
class A
{
};
class B
{
A objA;
};

class Employee
// composition
{ private: string name; unsigned int number;
public:
void getdata()
{cout << Enter last name: ; cin >> name;
cout << Enter number: ; cin >> number;}
void putdata()
{cout << Name: << name << endl;
cout << Number: << number << endl;}
};

class Manager
{ private: string title; Employee emp;
public:
void getdata()
{emp.getdata();
cout << Enter title: ; cin >> title;}
void putdata()
{emp.putdata();
cout << Title: << title << endl;}
};

int main()
{ Manager m1;
m1.getdata();
m1.putdata();
}

Run
Enter last name: Daniel
Enter number: 14404
Enter title: AM
Name: Daniel
Number: 14404
Title: AM

Inheritance
Inheritance is the process of creating new classes from
the existing classes.
When creating a class, instead of writing it from scratch,
we can designate that the new class should inherit the
members of an existing class.
The existing class is called the base class, and the new
class is referred to as the derived class.
A derived class represents a more specialized group of
objects. It contains behaviors inherited from the base
class plus additional behaviors.
A derived class can also customize behaviors inherited
from the base class.

A derived class can access the non-private members of its


base class.
A direct base class is the base class from which a derived
class explicitly inherits.

An indirect base class is inherited from two or more


levels up in the class hierarchy.
In case of single inheritance, a class is derived from a
single base class. In case of multiple inheritance, a class is
derived from multiple base classes.
When a class B is derived from another class A, we say
that B has an is-a relationship with A. In an is-a
relationship, an object of a derived class can also be
treated as an object of the base class.

CommunityMember

Student

Employee

Single inheritance
Faculty

Administrator

Staff

Teacher

AdministratorTeacher

Single inheritance

Single inheritance

Multiple inheritance

Protected members:
Other than private and public access specifiers, C++
provides another access specifier, called protected.
protected access provides an intermediate level of
protection between private and public.
A base classs protected members can be accessed within
the body of that base class, by members and friends of
that base class, and by members and friends of any class
derived from that base class.
Derived class member functions can refer to public and
protected members of the base class simply by using the
member names.

The syntax for defining a derived class is:


class base_class name
{
// body of base class
};
class derived_class name: accessSpecifier
base_class name
{
// body of derived class
};
accessSpecifier can be public or private or
protected keyword.

class Counter
// inheritance (adding -- operator
{ protected:
// along with ++ operator)
unsigned int count;
public:
Counter(): count(0)
{
}
Counter(int c): count(c)
{
}
unsigned int get_count()
{return count; }
Counter operator ++ ()
{return Counter(++count);}
};
class CountDn: public Counter
//derived class CountDn
{ public:
CountDn(): Counter()
// derived class constructor
{
}
CountDn(int c): Counter(c) // derived class constructor
{
}
CountDn operator -- ()
{return CountDn(--count);}
};

int main()
{CountDn c1, c2(100);
cout << \nc1 = << c1.get_count();
cout << \nc2 = << c2.get_count();
++c1; ++c1; ++c1;
cout << \nc1 = << c1.get_count();
--c2; --c2;
cout << \nc2 = << c2.get_count();
CountDn c3 = --c2;
cout << \nc3 = << c3.get_count();
}
Output:
c1 = 0
c2 = 100
c1 = 3
c2 = 98
C3 = 97

public, protected and private Inheritance:


A derived class may be derived from the base class through
public, protected or private inheritance.
Use of protected and private inheritance is rare.
When deriving a class from a public base class, public
members of the base class become public members of the
derived class, and the protected members of the base class
become the protected members of the derived class.
A base classs private members are not accessible directly
from a derived class, but can be accessed through calls to the
public or protected members of the base class.
When deriving from a protected base class, public and
protected members of the base class become protected
members of the derived class.

When deriving from a private base class, public and


protected members of the base class become private
members of the derived class. Therefore, objects of the
derived class cannot access these members directly.

Overriding Member Functions:


We can define functions with same names both in the base
class and the derived class.
When the same function is used in the base class and in
the derived class, the function in the derived class is
executed.
The base-class member function with same name can be
accessed from the derived class by preceding the baseclass member function name with the base-class name
followed by the binary scope resolution operator (::).

class A
// function overriding
{ public:
void f()
{cout << A::f() is executing << endl;}
};

class B: public A
// derived class
{ public:
void f()
{cout << B::f() is executing << endl;
A::f();
// calling f()of A
}
};

int main()
{A a1; B b1;
a1.f();
b1.f();
}

Run
A::f() is executing
B::f() is executing
A::f() is executing

enum poseneg{pos, neg};


//signed distance
class Distance
{ protected:
int feet; float inches;
public:
Distance(): feet(0), inches(0.0)
{ }
Distance(int ft, float in): feet(ft), inches(in)
{ }
void getdist()
{cout << "Enter feet " ; cin >> feet;
cout << "Enter inches "; cin >> inches; }
void showdist()
{cout << feet <<"\' - " << inches << '\"' << endl;}
};
class DistSign: public Distance
{ private: poseneg sign;
public:
DistSign(): Distance()
{sign = pos;}
DistSign(int ft, float in, poseneg sg = pos):Distance(ft, in)
{sign = sg;}

void getdist()
{Distance::getdist();
char ch;
cout << Enter sign (+ or -): ; cin >> ch;
sign = (ch ==+)? pos : neg;}
void showdist()
{cout << ((sign==pos) ? (+) : (-));
Distance::showdist();}
};
int main()
{DistSign alpha;
alpha.getdist();
DistSign beta(100, 6.25);
DistSign gamma(100, 5.5, neg);
cout << alpha = ; alpha.showdist();
cout << beta = ; beta.showdist();
cout << gamma = ; gamma.showdist();
}

Run:
Enter feet 10
Enter inches 4.5
Enter sign (+ or -): +
alpha = (+)10' - 4.5"
beta = (+)100' - 6.25"
gamma = (-)100' - 5.5

Constructors and Destructors in Derived Classes:


A derived class inherits data members and member
functions, but not the constructors or destructor from the
base class.
C++ requires that a derived class constructor call its baseclass constructor to initialize the base-class data members
that are inherited into the derived class.
Example: CountDn(): Counter()
{
}
CountDn(int c): Counter(c)
{
}

When an object of a derived class is created, the


constructor of the base class is executed first and then the
constructor of the derived class.

class B
{public:
B()
{cout <<Default constructor of the base-class is
executed" << endl;}
};
class D: public B
{public:
D()
{cout <<Default constructor of derived-class is
executed next" << endl;}
};
int main()
{D obj1;
}

Run:
Default constructor of the base-class is executed
Default constructor of derived-class is executed next

If the derived class does not have a constructor, the


compiler would attempt to invoke the default constructor
of the base class. If the base class does not have a default
constructor, the compiler will issue an error.
class B
{public: B()
{cout <<Default constructor of the base-class is
executed" << endl;}
};
class D: public B
{public:
};
Run:
int main()
Default constructor of the base-class is executed
{D obj1;
}

If the base class is derived from the another class, the


base-class constructor is required to invoke the
constructor of the next class up in the hierarchy, and so
on.
The last constructor called in this chain is the constructor
of the class at the base of the hierarchy, whose body is
finishes executing first. The original derived-classs
constructor finishes executing last.
Each base-class constructor initializes the base-class data
members that the derived class inherits.
The destructor are executed in the reverse order of the
execution of constructors. The derived classs destructor
is executed first, then the destructor of the next class up in
the hierarchy, and so on.

Multiple Inheritance:
A class can be derived from more than one base class.
This is called multiple inheritance.
The syntax for multiple inheritance is similar to that for
single inheritance.
class A
{
};
class B
{
};
class C: public A, public B
{
};

class Employee
// multiple inheritance
{ private: char name[50]; unsigned int number;
public:
void getdata()
{cout << Enter last name: ; cin >> name;
cout << Enter number: ; cin >> number;}
void putdata()
{cout << Name: << name << endl;
cout << Number: << number << endl;}
};

class Student
{ private: char degree[20];
public:
void getedu()
{cout << Enter highest degree earned : ;
cin >> degree;}
void putedu()
{cout << Highest degree earned:\n << degree ;}
};

class Manager: public Employee, public Student


{ private: char title[20];
public:
void getdata()
{Employee::getdata();
cout << Enter title: ; cin >> title;
Student::getedu();}
void putdata()const
{Employee::putdata();
cout << Title: << title << endl;
Student::putedu();}
};
Run:
Enter last name: Daniel
Enter number: 14404
int main()
Enter title: AM
{Manager m1;
Enter highest degree earned : M.B.A.
m1.getdata();
m1.putdata();
Name: Daniel
Number: 14404
}
Title: AM
Highest degree earned: M.B.A.

Constructors in Multiple Inheritance:


The base class constructors are always executed first,
working from the first base class to the last base class and
finally through the derived class constructor. For example
if we have the multiple inheritance
class C: public A, public B

then the constructor of the base class A is executed first,


followed by the constructor of B and finally the
constructor of the derived class C.
The destructors are invoked in the reverse order of the
constructor invocation.
Some or all parameters that are supplied to a derived class
constructor may be passed to the base class(es)
constructor. This is illustrated by the following program:

class A
// parameter passing to constructors
{ public:
A(char a)
{cout << a <<endl;}
};
class B
{ public:
B(char b)
{cout << b <<endl;}
};
class C: public A, public B
{ public:
C(char c1, char c2, char c3): A(c1), B(c2)
{cout << c3 <<endl;}
};
Run:
int main()
a
{C objc(a, b, c);
b
}
c

Polymorphism
The term polymorphism is used in C++ to refer to the
form of a member function that can be changed at
runtime.
Such member functions are called virtual functions and
the corresponding class is called a polymorphic class.
The objects of the polymorphic class change at runtime
and respond differently for the same message.
Such a mechanism requires postponement of binding a
function call to the member function until runtime.

Example:
Suppose a graphic program includes several different shapes: a
triangle, a ball, a square, and so on. Also suppose that each of
these classes has a member function draw().
Now suppose we want to make a picture by grouping a number of
these elements together. One approach to do this is by creating an
array that holds pointers to all the different objects in the picture:
shape* ptrarr[100];
We can then draw the whole picture by using a simple loop:
for(i=0; i< n; i++)
ptrarr -> draw();
By this, completely different functions are executed by the same
function call.
For this approach to work, following conditions must be met:
1.
2.

All the different classes of shape must be derived from a single base class.
The draw() function must be declared to be virtual in the base class.

The syntax for declaring a virtual function is:


virtual returnType functionName(arguments)
{
}

Base-class Pointers to Derived Class Objects:


A program can create an array of base-class pointers that
points to objects of many derived-class types. Even
though the derived class objects are of different types,
the compiler allows this because each derived-class
object is an object of its base-class.
The polymorphism occurs when a program invokes a
virtual function through a base-class pointer or reference.
C++ dynamically chooses the correct function for the
class from which the object was created.

By a base-class pointer, the compiler allows us to invoke


only base class member functions. An attempt to access a
derived-class-only member function by a base-class
pointer, a compilation error will occur.

class Base
// Member functions accessed with pointers
{public:
void show()
{cout << Base << endl;}
};
class Derv1: public Base

{public:
void show()
{cout << Derv1 << endl;}
};
class Derv2: public Base

{public:
void show()
{cout << Derv2 << endl;}
};
int main()
{Derv1 dv1; Derv2 dv2;
Base* ptr;
ptr = &dv1;
ptr -> show();
ptr = &dv2;
ptr -> show();
}

Run:
Base
Base
//ptr->show() does the same work , irrespective
of the object it is working on.

class Base
// Virtual functions accessed with pointers
{public:
virtual void show()
{cout << Base << endl;}
};
class Derv1: public Base
{public:
void show()
{cout << Derv1 << endl;}
};
class Derv2: public Base
void show()
{public:
{cout << Derv2 << endl;}
};
int main()
{Derv1 dv1; Derv2 dv2;
Base* ptr;
ptr = &dv1;
ptr -> show();
ptr = &dv2;
ptr -> show();
}

Run:
Derv1
Derv2
//ptr->show() executes different functions,
depending on the content of the pointer.

Dynamic (or Late) Binding:


If a program invokes a virtual function through a baseclass pointer to a derived class object, such as,
ptrarr -> draw();

the program will choose the correct derived-class draw()


function dynamically based on the object type.
Choosing the appropriate function to call at execution
time is known as late binding or dynamic binding.
When a virtual function is called by referencing a specific
object by name and using the dot operator, such as,
squareObject.draw();

the function invocation is resolved at compile time. This


is called static binding. This is not polymorphic behavior.

class Graphics
// Member functions accessed with pointers
{public:
virtual void draw()
{cout << point << endl;}
};
class Triangle: public Graphics
{public:
void draw()
{cout << triangle << endl;}
};
class Rectangle: public Graphics
{public:
void draw()
{cout << rectangle << endl;}
};
class Circle: public Graphics
{public:
void draw()
{cout << circle << endl;}
};

int main()
{Graphics* gptrarr[4];
gptrarr[0]= new Graphics;
gptrarr[1]= new Triangle;
gptrarr[2]= new Rectangle;
gptrarr[3]= new Circle;
for(int i=0; i<4; i++)
{gptrarr[i] -> draw();}
}

Run:
point
triangle
rectangle
circle

Pure Virtual Functions:


There are certain base classes whose objects are never
instantiated. Such a class is called an abstract class.
Such a class exists only to act as a parent of derived
classes that will be used to instantiate objects.
For example, the shape class is an abstract class; we
will only make specific shapes such as circles and
triangles.
Abstract classes are defined by placing in them at least
one pure virtual function.
A purely virtual function is one with the expression = 0
added to the declaration:
virtual void draw() = 0;

class Graphics
// Member functions accessed with pointers
{public:
virtual void draw() = 0;
};
class Triangle: public Graphics
{public:
void draw()
{cout << "triangle" << endl;}
};
class Rectangle: public Graphics
{public:
void draw()
{cout << "rectangle" << endl;}
};
class Circle: public Graphics
{public:
void draw()
{cout << "circle" << endl;}
};

int main()
{
Graphics* gptrarr[3];
gptrarr[0]= new Triangle;
gptrarr[1]= new Rectangle;
gptrarr[2]= new Circle;
for(int i=0; i<3; i++)
{gptrarr[i] -> draw();
}
Run:
triangle
rectangle
circle

You might also like