Professional Documents
Culture Documents
Unit 5 C++
Unit 5 C++
Unit 5 C++
Inheritance
C++ Inheritance
In C++, inheritance is a process in which one object acquires all the properties and
behaviors of its parent object automatically. In such way, you can reuse, extend or modify
the attributes and behaviors which are defined in other class.
In C++, the class which inherits the members of another class is called derived class and
the class whose members are inherited is called base class. The derived class is the
specialized class for the base class.
// Base class
class Shape {
public:
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Derived class
class Rectangle: public Shape {
public:
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
Rect.setWidth(5);
Rect.setHeight(7);
return 0;
}
When the above code is compiled and executed, it produces the following result −
Total area: 35
A derived class inherits all base class methods with the following exceptions −
Types of Inheritance
C++ supports five types of inheritance:
o Single inheritance
o Multiple inheritance
o Hierarchical inheritance
o Multilevel inheritance
o Hybrid inheritance
Derived Classes
A Derived class is defined as the class derived from the base class.
Where,
o When the base class is privately inherited by the derived class, public members of
the base class becomes the private members of the derived class. Therefore, the
public members of the base class are not accessible by the objects of the derived
class only by the member functions of the derived class.
o When the base class is publicly inherited by the derived class, public members of the
base class also become the public members of the derived class. Therefore, the
public members of the base class are accessible by the objects of the derived class
as well as by the member functions of the base class.
Note:
Where 'A' is the base class, and 'B' is the derived class.
Output:
Salary: 60000
Bonus: 5000
In the above example, Employee is the base class and Programmer is the derived class.
1. #include <iostream>
2. using namespace std;
3. class Animal {
4. public:
5. void eat() {
6. cout<<"Eating..."<<endl;
7. }
8. };
9. class Dog: public Animal
10. {
11. public:
12. void bark(){
13. cout<<"Barking...";
14. }
15. };
16. int main(void) {
17. Dog d1;
18. d1.eat();
19. d1.bark();
20. return 0;
21. }
Output:
Eating...
Barking...
1. #include <iostream>
2. using namespace std;
3. class A
4. {
5. int a = 4;
6. int b = 5;
7. public:
8. int mul()
9. {
10. int c = a*b;
11. return c;
12. }
13. };
14.
15. class B : private A
16. {
17. public:
18. void display()
19. {
20. int result = mul();
21. std::cout <<"Multiplication of a and b is : "<<result<< std::endl;
22. }
23. };
24. int main()
25. {
26. B b;
27. b.display();
28.
29. return 0;
30. }
Output:
Multiplication of a and b is : 20
In the above example, class A is privately inherited. Therefore, the mul() function of class
'A' cannot be accessed by the object of class B. It can only be accessed by the member
function of class B.
C++ introduces a third visibility modifier, i.e., protected. The member which is declared as
protected will be accessible to all the member functions within the class as well as the class
immediately derived from it.
o Public: When the member is declared as public, it is accessible to all the functions of
the program.
o Private: When the member is declared as private, it is accessible within the class
only.
o Protected: When the member is declared as protected, it is accessible within its
own class as well as the class immediately derived from it.
1. #include <iostream>
2. using namespace std;
3. class Animal {
4. public:
5. void eat() {
6. cout<<"Eating..."<<endl;
7. }
8. };
9. class Dog: public Animal
10. {
11. public:
12. void bark(){
13. cout<<"Barking..."<<endl;
14. }
15. };
16. class BabyDog: public Dog
17. {
18. public:
19. void weep() {
20. cout<<"Weeping...";
21. }
22. };
23. int main(void) {
24. BabyDog d1;
25. d1.eat();
26. d1.bark();
27. d1.weep();
28. return 0;
29. }
Output:
Eating...
Barking...
Weeping...
1. #include <iostream>
2. using namespace std;
3. class A
4. {
5. protected:
6. int a;
7. public:
8. void get_a(int n)
9. {
10. a = n;
11. }
12. };
13.
14. class B
15. {
16. protected:
17. int b;
18. public:
19. void get_b(int n)
20. {
21. b = n;
22. }
23. };
24. class C : public A,public B
25. {
26. public:
27. void display()
28. {
29. std::cout << "The value of a is : " <<a<< std::endl;
30. std::cout << "The value of b is : " <<b<< std::endl;
31. cout<<"Addition of a and b is : "<<a+b;
32. }
33. };
34. int main()
35. {
36. C c;
37. c.get_a(10);
38. c.get_b(20);
39. c.display();
40.
41. return 0;
42. }
Output:
The value of a is : 10
The value of b is : 20
Addition of a and b is : 30
In the above example, class 'C' inherits two base classes 'A' and 'B' in a public mode.
1. #include <iostream>
2. using namespace std;
3. class A
4. {
5. public:
6. void display()
7. {
8. std::cout << "Class A" << std::endl;
9. }
10. };
11. class B
12. {
13. public:
14. void display()
15. {
16. std::cout << "Class B" << std::endl;
17. }
18. };
19. class C : public A, public B
20. {
21. void view()
22. {
23. display();
24. }
25. };
26. int main()
27. {
28. C c;
29. c.display();
30. return 0;
31. }
Output:
1. class A
2. {
3. public:
4. void display()
5. {
6. cout<<?Class A?;
7. }
8. } ;
9. class B
10. {
11. public:
12. void display()
13. {
14. cout<<?Class B?;
15. }
16. } ;
In the above case, the function of the derived class overrides the method of the base class.
Therefore, call to the display() function will simply call the function defined in the derived
class. If we want to invoke the base class function, we can use the class resolution operator.
1. int main()
2. {
3. B b;
4. b.display(); // Calling the display() function of B class.
5. b.B :: display(); // Calling the display() function defined in B class.
6. }
1. #include <iostream>
2. using namespace std;
3. class A
4. {
5. protected:
6. int a;
7. public:
8. void get_a()
9. {
10. std::cout << "Enter the value of 'a' : " << std::endl;
11. cin>>a;
12. }
13. };
14.
15. class B : public A
16. {
17. protected:
18. int b;
19. public:
20. void get_b()
21. {
22. std::cout << "Enter the value of 'b' : " << std::endl;
23. cin>>b;
24. }
25. };
26. class C
27. {
28. protected:
29. int c;
30. public:
31. void get_c()
32. {
33. std::cout << "Enter the value of c is : " << std::endl;
34. cin>>c;
35. }
36. };
37.
38. class D : public B, public C
39. {
40. protected:
41. int d;
42. public:
43. void mul()
44. {
45. get_a();
46. get_b();
47. get_c();
48. std::cout << "Multiplication of a,b,c is : " <<a*b*c<< std::endl;
49. }
50. };
51. int main()
52. {
53. D d;
54. d.mul();
55. return 0;
56. }
Output:
1. class A
2. {
3. // body of the class A.
4. }
5. class B : public A
6. {
7. // body of class B.
8. }
9. class C : public A
10. {
11. // body of class C.
12. }
13. class D : public A
14. {
15. // body of class D.
16. }
1. #include <iostream>
2. using namespace std;
3. class Shape // Declaration of base class.
4. {
5. public:
6. int a;
7. int b;
8. void get_data(int n,int m)
9. {
10. a= n;
11. b = m;
12. }
13. };
14. class Rectangle : public Shape // inheriting Shape class
15. {
16. public:
17. int rect_area()
18. {
19. int result = a*b;
20. return result;
21. }
22. };
23. class Triangle : public Shape // inheriting Shape class
24. {
25. public:
26. int triangle_area()
27. {
28. float result = 0.5*a*b;
29. return result;
30. }
31. };
32. int main()
33. {
34. Rectangle r;
35. Triangle t;
36. int length,breadth,base,height;
37. std::cout << "Enter the length and breadth of a rectangle: " << std::endl;
38. cin>>length>>breadth;
39. r.get_data(length,breadth);
40. int m = r.rect_area();
41. std::cout << "Area of the rectangle is : " <<m<< std::endl;
42. std::cout << "Enter the base and height of the triangle: " << std::endl;
43. cin>>base>>height;
44. t.get_data(base,height);
45. float n = t.triangle_area();
46. std::cout <<"Area of the triangle is : " << n<<std::endl;
47. return 0;
48. }
Output:
int main()
{
Base *b;
Derived d;
b = &d;
b->show();
}
Polymorphism in C++
The word polymorphism means having many forms. In simple words, we can define
polymorphism as the ability of a message to be displayed in more than one form.
Real life example of polymorphism, a person at the same time can have different characteristic.
Like a man at the same time is a father, a husband, an employee. So the same person posses
different behavior in different situations. This is called polymorphism.
Polymorphism is considered as one of the important features of Object Oriented Programming.
In C++ polymorphism is mainly divided into two types:
Compile time Polymorphism
Runtime Polymorphism
Function Overloading: When there are multiple functions with same name but
different parameters then these functions are said to be overloaded. Functions can be
overloaded by change in number of arguments or/and change in type of
arguments.
Rules of Function Overloading
// C++ program for function overloading
#include <bits/stdc++.h>
int main() {
Geeks obj1;
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i =0) {real = r; imag = i;}
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // An example call to "operator+"
c3.print();
}
Output:
12 + i9
In the above example the operator ‘+’ is overloaded. The operator ‘+’ is an addition
operator and can add two numbers(integers or floating point) but here the operator is
made to perform addition of two imaginary or complex numbers. To learn operator
overloading in details visit this link.
2. Runtime polymorphism: This type of polymorphism is achieved by Function Overriding.
Function overriding on the other hand occurs when a derived class has a definition
for one of the member functions of the base class. That base function is said to
be overridden.
// C++ program for function overriding
#include <bits/stdc++.h>
using namespace std;
class base
{
public:
virtual void print ()
{ cout<< "print base class" <<endl; }
void show ()
{ cout<< "show base class" <<endl; }
};
void show ()
{ cout<< "show derived class" <<endl; }
};
//main function
int main()
{
base *bptr;
derived d;
bptr = &d;
return 0;
}
Output:
print derived class
show base class
C++ Polymorphism. Polymorphism means more than one function with same
name, with different working. ... Virtual function is an example of dynamic
polymorphism. Static polymorphism is also known as early binding and compile-
time polymorphism. Dynamic polymorphism is also known as late binding and
run-time polymorphism.
Polymorphism means more than one function with same name, with different working.
Polymorphism can be static or dynamic. In static polymorphism memory will be
allocated at compile-time. In dynamic polymorphism memory will be allocated at run-
time. Both function overloading and operator overloading are an examples of static
polymorphism. Virtual function is an example of dynamic polymorphism.
Static polymorphism is also known as early binding and compile-time
polymorphism.
Dynamic polymorphism is also known as late binding and run-time
polymorphism.
Pointers to Objects
A variable that holds an address value is called a pointer variable or simply pointer.
Pointer can point to objects as well as to simple data types and arrays.
sometimes we dont know, at the time that we write the program , how many objects we want to creat.
when this is the case we can use new to creat objects while the program is running. new returns a
pointer to an unnamed objects. lets see the example of student that wiil clear your idea about this topic
#include <iostream>
#include <string>
using namespace std;
class student
{
private:
int rollno;
string name;
public:
student():rollno(0),name("")
{}
student(int r, string n): rollno(r),name (n)
{}
void get()
{
cout<<"enter roll no";
cin>>rollno;
cout<<"enter name";
cin>>name;
}
void print()
{
cout<<"roll no is "<<rollno;
cout<<"name is "<<name;
}
};
void main ()
{
student *ps=new student;
(*ps).get();
(*ps).print();
delete ps;
}
Meaning each object gets its own copy of data members and all objects share a single
copy of member functions.
Then now question is that if only one copy of each member function exists and is used
by multiple objects, how are the proper data members are accessed and updated?
The compiler supplies an implicit pointer along with the names of the functions as ‘this’.
The ‘this’ pointer is passed as a hidden argument to all nonstatic member function calls
and is available as a local variable within the body of all nonstatic functions. ‘this’ pointer
is not available in static member functions as static member functions can be called
without any object (with class name).
For a class X, the type of this pointer is ‘X* ‘. Also, if a member function of X is declared
as const, then the type of this pointer is ‘const X *’ (see this GFact)
In the early version of C++ would let ‘this’ pointer to be changed; by doing so a
programmer could change which object a method was working on. This feature was
eventually removed, and now this in C++ is an r-value.
As Stroustrup said ‘this’ could be the reference than the pointer, but the reference was
not present in the early version of C++. If ‘this’ is implemented as a reference then, the
above problem could be avoided and it could be safer than the pointer.
Following are the situations where ‘this’ pointer is used:
1) When local variable’s name is same as member’s name
#include<iostream>
using namespace std;
int main()
{
Test obj;
int x = 20;
obj.setX(x);
obj.print();
return 0;
}
Output:
x = 20
For constructors, initializer list can also be used when parameter name is same as
member’s name.
class Test
{
private:
int x;
int y;
public:
Test(int x = 0, int y = 0) { this->x = x; this->y = y; }
Test &setX(int a) { x = a; return *this; }
Test &setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1(5, 5);
obj1.print();
return 0;
}
Output:
x = 10 y = 20
Exercise:
Predict the output of following programs. If there are compilation errors, then fix them.
Question 1
#include<iostream>
using namespace std;
class Test
{
private:
int x;
public:
Test(int x = 0) { this->x = x; }
void change(Test *t) { this = t; }
void print() { cout << "x = " << x << endl; }
};
int main()
{
Test obj(5);
Test *ptr = new Test (10);
obj.change(ptr);
obj.print();
return 0;
}
Question 2
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test(int x = 0, int y = 0) { this->x = x; this->y = y; }
static void fun1() { cout << "Inside fun1()"; }
static void fun2() { cout << "Inside fun2()"; this->fun1(); }
};
int main()
{
Test obj;
obj.fun2();
return 0;
}
Question 3
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test(int x = 0, int y = 0) { this->x = x; this->y = y; }
void setX(int a) { x = a; }
void setY(int b) { y = b; }
void destroy() { delete this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj;
obj.destroy();
obj.print();
return 0;
}
In C++, we can declare a pointer points to the base class as well as derive class.
Consider below example to understand pointer to derived class
#include<iostream.h>
class base
public:
int n1;
void show()
cout<<”\nn1 = “<<n1;
};
public:
int n2;
void show()
cout<<”\nn1 = “<<n1;
cout<<”\nn2 = “<<n2;
};
int main()
base b;
bptr->show();
derive d;
cout<<”\n”;
bptr=&d; //address of derive class
bptr->n1=66; //access derive class via base pointer
bptr->show();
return 0;
}
Output
Pointer of base class points to it
n1 = 44
Pointer of base class points to derive class
n1=66
Here the show() method is the overridden method, bptr execute show() method of ‘base’ class twice and
display its content. Even though bptr first points to ‘base’ and second time points to ‘derive’ ,both the time
bptr->show() executes the ‘base’ method show()
Before going into detail, let's build an intuition on why virtual functions are
needed in the first place.
We created the Weapon class and derived two classes Bomb and Gun to load
features of respective weapons.
#include <iostream>
using namespace std;
class Weapon
{
public:
void loadFeatures()
{ cout << "Loading weapon features.\n"; }
};
int main()
{
Weapon *w = new Weapon;
Bomb *b = new Bomb;
Gun *g = new Gun;
w->loadFeatures();
b->loadFeatures();
g->loadFeatures();
return 0;
}
Output
w->loadFeatures();
b->loadFeatures();
g->loadFeatures();
Works perfectly!
However, our game project started getting bigger and bigger. And, we decided
to create a separate Loader class to load weapon features.
This Loader class loads additional features of a weapon depending on which
weapon is selected.
class Loader
{
public:
void loadFeatures(Weapon *weapon)
{
weapon->features();
}
};
#include <iostream>
using namespace std;
class Weapon {
public:
Weapon() { cout << "Loading weapon features.\n"; }
Output
Initially, the Weapon object w is pointing to the b object (of Bomb) class. And,
we tried to load the features of Bomb object by passing it
to loadFeatures() function using l object to pointer (of Loader class).
Similarly, we tried to load the features of Gun object.
However, the loadFeatures() function of the Loader class takes pointer to object
of a Weapon class as an argument:
That's the reason weapon features are loaded 4 times. To solve this issue, we
need to make function of base class ( Weapon class) virtual using virtual
keyword.
class Weapon
{
public:
virtual void features()
{ cout << "Loading weapon features.\n"; }
};
#include <iostream>
using namespace std;
class Weapon
{
public:
virtual void features()
{ cout << "Loading weapon features.\n"; }
};
class Loader
{
public:
void loadFeatures(Weapon *weapon)
{
weapon->features();
}
};
int main()
{
Loader *l = new Loader;
Weapon *w;
Bomb b;
Gun g;
w = &b;
l->loadFeatures(w);
w = &g;
l->loadFeatures(w);
return 0;
}
Output
If we want to add another weapon (let's say knife), we can easily add and load
features of it. How?
Knife k;
w = &k;
l->loadFeatures(w);
It's worth noticing that we didn't change anything in the Loader class to load
features of knife.
Sometimes, it's desirable to use inheritance just for the case of better
visualization of the problem.
In C++, you can create an abstract class that cannot be instantiated (you
cannot create object of that class). However, you can derive a class from it
and instantiate object of the derived class.
#include <iostream>
using namespace std;
class Weapon
{
public:
virtual void features()
{ cout << "Loading weapon features.\n"; }
};
class Loader
{
public:
void loadFeatures(Weapon *weapon)
{
weapon->features();
}
};
int main()
{
Loader *l = new Loader;
Weapon *w;
Bomb b;
Gun g;
w = &b;
l->loadFeatures(w);
w = &g;
l->loadFeatures(w);
return 0;
}
Output
Also, notice that, the l->loadFeatures(w) function calls the function of different
classes depending upon what l object is pointing.
Using virtual function made our code not only clearer but flexible too.
If we want to add another weapon (let's say knife), we can easily add and load
features of it. How?
Knife k;
w = &k;
l->loadFeatures(w);
It's worth noticing that we didn't change anything in the Loader class to load
features of knife.
C++ Abstract class and Pure virtual Function
The goal of object-oriented programming is to divide a complex problem into
small sets. This helps understand and work with problem in an efficient way.
Sometimes, it's desirable to use inheritance just for the case of better
visualization of the problem.
In C++, you can create an abstract class that cannot be instantiated (you
cannot create object of that class). However, you can derive a class from it
and instantiate object of the derived class.
class Weapon
public:
};
#include <iostream>
using namespace std;
// Abstract class
class Shape
{
protected:
float l;
public:
void getData()
{
cin >> l;
}
// virtual Function
virtual float calculateArea() = 0;
};
int main()
{
Square s;
Circle c;
return 0;
}
Output
In this program, pure virtual function virtual float area() = 0; is defined inside
the Shape class.
One important thing to note is that, you should override the pure virtual
function of the base class in the derived class. If you fail the override it, the
derived class will become an abstract class as well.