Unit 3 - Oops
Unit 3 - Oops
Unit 3 - Oops
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.
Types Of Inheritance
C++ supports five types of inheritance:
o Single inheritance
o Multiple inheritance
o Hierarchical inheritance
o Multilevel inheritance
o Hybrid inheritance
1 NOTES BY A V MAHALLE
Derived Classes
A Derived class is defined as the class derived from the base class.
visibility mode: The visibility mode specifies whether the features of the base class are publicly
inherited or privately inherited. It can be public or private.
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:
o In C++, the default mode of visibility is private.
o The private members of the base class are never inherited.
2 NOTES BY A V MAHALLE
Where 'A' is the base class, and 'B' is the derived class.
1. #include <iostream>
2. using namespace std;
3. class Account {
4. public:
5. float salary = 60000;
6. };
7. class Programmer: public Account {
8. public:
9. float bonus = 5000;
10. };
11. int main(void) {
12. Programmer p1;
13. cout<<"Salary: "<<p1.salary<<endl;
14. cout<<"Bonus: "<<p1.bonus<<endl;
15. return 0;
16. }
Output:
Salary: 60000
Bonus: 5000
In the above example, Employee is the base class and Programmer is the derived class.
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. }
4 NOTES BY A V MAHALLE
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.
Visibility modes can be classified into three categories:
5 NOTES BY A V MAHALLE
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:
6 NOTES BY A V MAHALLE
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...
7 NOTES BY A V MAHALLE
Syntax of the Derived class:
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;
8 NOTES BY A V MAHALLE
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()
9 NOTES BY A V MAHALLE
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:
o The above issue can be resolved by using the class resolution operator with the function. In the above
example, the derived class code can be rewritten as:
1. class A
2. {
3. public:
10 NOTES BY A V MAHALLE
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. }
11 NOTES BY A V MAHALLE
Let's see a simple example:
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
12 NOTES BY A V MAHALLE
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. {
13 NOTES BY A V MAHALLE
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
14 NOTES BY A V MAHALLE
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:
15 NOTES BY A V MAHALLE
constructors and destructors in derived classes in cpp
In C++, constructors and destructors are special member functions that are used to initialize and clean up
objects of a class, respectively. When dealing with derived classes (also known as subclasses), which inherit
properties and behavior from a base class (also known as a superclass), constructors and destructors
behave in a specific way.
Let's break down constructors and destructors in the context of derived classes:
1. Constructors in Derived Classes:
When you create an object of a derived class, its constructor is responsible for initializing both the
derived class's attributes and the inherited attributes from the base class. This involves invoking
the base class's constructor before initializing the specific attributes of the derived class. This can
be achieved using an initializer list in the derived class's constructor.
class Base
{
public:
Base(int val)
{ /* constructor logic */ }
};
2. Destructors in Derived Classes: When an object of a derived class goes out of scope or is explicitly
deleted, its destructor is called. Similar to constructors, destructors follow an order from derived
class to base class. First, the derived class's destructor is executed, followed by the base class's
destructor. This ensures that any resources acquired in the derived class are released properly
before moving up the inheritance chain.
class Base
{
public:
~Base()
{ /* destructor logic */ }
};
16 NOTES BY A V MAHALLE
class Derived : public Base
{
public:
~Derived()
{ // Cleanup Derived-specific resources }
};
To summarize, constructors in derived classes handle initialization of both the derived and base class
members, while destructors in derived classes handle cleanup in reverse order, ensuring that resources are
released properly.
Example:
#include <iostream>
class Animal {
protected:
std::string mName;
public:
Animal(const std::string& name) : mName(name) {
std::cout << "Animal constructor: " << mName << std::endl;
}
~Animal() {
std::cout << "Animal destructor: " << mName << std::endl;
}
};
public:
Dog(const std::string& name, const std::string& breed) : Animal(name), mBreed(breed) {
std::cout << "Dog constructor: " << mName << ", Breed: " << mBreed << std::endl;
}
~Dog() {
std::cout << "Dog destructor: " << mName << ", Breed: " << mBreed << std::endl;
}
};
int main() {
17 NOTES BY A V MAHALLE
Dog myDog("Buddy", "Golden Retriever");
return 0;
}
Output:
Animal constructor: Buddy
Dog constructor: Buddy, Breed: Golden Retriever
Dog destructor: Buddy, Breed: Golden Retriever
Animal destructor: Buddy
Explanation:
class Animal {
public:
Animal(const std::string& name) : mName(name) {
std::cout << "Animal constructor: " << mName << std::endl;
}
Here, we define a class Animal with a constructor that takes a name parameter and initializes the private
member mName with the provided value. Inside the constructor, a message is printed indicating that the
Animal constructor is being called, along with the name of the animal.
&: The ampersand (&) symbol in const std::string& denotes that name is a reference to a std::string. In
C++, when you pass an argument by reference, you are essentially passing a reference to the original
object rather than making a copy of it. This can be more efficient than passing objects by value,
especially for large objects like strings.
Here, we define a derived class Dog that publicly inherits from the Animal base class. The derived class
has a constructor Dog(const std::string& name, const std::string& breed) which takes both a name and a
breed parameter. This constructor first calls the Animal constructor to initialize the base class part of
the Dog object. Then, it initializes the protected member mBreed with the provided breed value. It prints
a message indicating that the Dog constructor is being called, along with the name and breed of the dog.
18 NOTES BY A V MAHALLE
class base
{
//Data Members
//Member Functions
};
class derived : public base
{
//Data Members
//Member functions
};
void main ( )
{
base *ptr; //pointer to class base derived obj ;
ptr = &obj ;//indirect reference obj to the pointer
//Other Program statements
}
Example:
#include <iostream>#include <iostream>
// Base class
class Base {
public:
void Show() {
std::cout << "Common function in the base class" << std::endl;
}
};
// Derived class
class Derived : public Base {
public:
void Display() {
std::cout << "Derived class function" << std::endl;
}
};
int main() {
Base b;
Derived d;
return 0;
}
Output:
Common function in the base class
Common function in the base class
Derived class function
Pointers can be declared to derived class.It can be used to access members of base class
and derived class. A base class pointer can also be used to point to object of derived class
but it can access only members that are inherited from base class.
20 NOTES BY A V MAHALLE
4. They can be a friend of another class.
5. A virtual function must be defined in the base class, even though it is not used.
6. The prototypes of a virtual function of the base class and all the derived classes must be identical. If
the two functions with the same name but different prototypes, C++ will consider them as the
overloaded functions.
7. We cannot have a virtual constructor, but we can have a virtual destructor
Consider the situation when we don't use the virtual keyword.
#include <iostream>
using namespace std;
class A
{
int x=5;
public:
void display()
{
std::cout << "Value of x is : " << x<<std::endl;
}
};
class B: public A
{
int y = 10;
public:
void display()
{
std::cout << "Value of y is : " <<y<< std::endl;
}
};
int main()
{
A *a;
B b;
a = &b;
a->display();
return 0;
}
Output:
Value of x is : 5
In the above example, * a is the base class pointer. The pointer can only access the base class members but
not the members of the derived class. Although C++ permits the base pointer to point to any object
derived from the base class, it cannot directly access the members of the derived class. Therefore, there is
a need for virtual function which allows the base pointer to access the members of the derived class.
21 NOTES BY A V MAHALLE
Let's see the simple example of C++ virtual function used to invoked the derived class in a program.
#include <iostream>
{
public:
virtual void display()
{
cout << "Base class is invoked"<<endl;
}
};
class B:public A
{
public:
void display()
{
cout << "Derived Class is invoked"<<endl;
}
};
int main()
{
A* a; //pointer of base class
B b; //object of derived class
a = &b;
a->display(); //Late Binding occurs
}
Output:
22 NOTES BY A V MAHALLE
#include <iostream>
using namespace std;
class Base
{
public:
virtual void show() = 0;
};
class Derived : public Base
{
public:
void show()
{
std::cout << "Derived class is derived from the base class." << std::endl;
}
};
int main()
{
Base *bptr;
//Base b;
Derived d;
bptr = &d;
bptr->show();
return 0;
}
Output:
Derived class is derived from the base class.
In the above example, the base class contains the pure virtual function. Therefore, the base class is an
abstract base class. We cannot create the object of the base class.
class Shape {
public:
23 NOTES BY A V MAHALLE
virtual void area() const = 0; // Pure virtual function
};
public:
Circle(double r) : radius(r) {}
In this example, the Shape class is abstract due to the pure virtual function area(). The Circle class is a
concrete class that derives from Shape and provides an implementation for the pure virtual function.
Abstract Types:
An abstract type is a class that contains one or more pure virtual functions, making it impossible to create
instances of that class directly. Abstract types are used as base classes for creating derived classes with
specific implementations. They are often used to define interfaces or common behaviors for a group of
related classes.
Example:
class Animal {
public:
virtual void speak() const = 0; // Pure virtual function
};
24 NOTES BY A V MAHALLE
In this example, the Animal class is an abstract type with a pure virtual function speak(). The Dog and Cat
classes are derived classes that provide specific implementations of the speak() function.
Abstract types and pure virtual functions enable polymorphism, allowing you to write code that works with
objects of different derived classes through pointers or references to the abstract base class. This is a
powerful mechanism for achieving runtime polymorphism and code flexibility in C++.
Example:
class Base {
public:
void show() {
std::cout << "Base class" << std::endl;
}
};
int main() {
Base obj1;
Derived obj2;
Base* ptr = &obj2;
Example:
class Base {
public:
virtual void show() {
std::cout << "Base class" << std::endl;
}
};
int main() {
Base obj1;
Derived obj2;
Base* ptr = &obj2;
In this example, the show() method is marked as virtual, enabling late binding. When calling ptr->show(),
the decision about which function to call is determined at runtime based on the actual type of the object
pointed to by ptr, resulting in the call to Derived::show().
Late binding is a fundamental feature in achieving polymorphism and is commonly used when you want to
work with objects of derived classes through pointers or references to their base class, allowing for
flexibility and extensibility in your code.
26 NOTES BY A V MAHALLE