Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
8 views

Module 3_OOPs

Uploaded by

Aman Singh
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

Module 3_OOPs

Uploaded by

Aman Singh
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 31

Modue -: 3 Inheritance

 Inheritance is the specific feature of c++


 Inheritance is the process of writing a new class by using existing class functionality
 Existing class is called as super class or base class or parent class
 New class is called as sub class or derived class or child class
 Main use of inheritance is code reusability
 This concept is used to reduce the complexity of large programme
 As per requirement we use another part of class known as protected part it property
lies between private and public
 Two parts of the class could be inherited public part and protected part
 In this situation derived class has its own property as well as it can assess public and
protected part of the base class
 Class could be inherited in two different modes First
1. Private mode of inheritance-:
 In this mode of inheritance protected and public part of base class
becomes private for derived class.
 It makes the programme difficult thus it is ignored hello

2. Public mode of inheritance -:


 In this mode all public and protected part of the base class remains
public for derived class also
 This mode of inhibence is frequently used.

Syntax-: and then there is a narrow focus on the wave coming there are
class base_class{

 we create the object of last derived class always and a specific class which doesn’t consider
objects is known as abstract class.

 Following our various type of inheritance


1. Simple inheritance
2. Multi level inheritance
3. Hierarchical inheritance
4. Multiple inheritance
5. Hybrid inheritance

1. SIMPLE INHERITANCE-:

B
 Mirror In simple inheritance there will be only one super class and one subclass.

2. Multilevel inheritance-:

 In multi level inheritance one super class can have only one direction class and many indirect
classes.
 One sub class can have only one direction super class and many indirect super class
3. Hierarchical inheritance:-

B C D

 In this one super class can have many direct super class but one super class can
have only one sub class.

4. Multiple inheritances:-

A B C

D
 In this one sub class can have many direct super class but one super class can
have only one sub class.
5. Hybrid inheritance:-

B C D

B C D

E F

 It is the combination of more than one type of inheritance i.e hybrid variety of
inheritance.

Abstract Class
A class that contains a pure virtual function is known as an abstract class. In the
above example, the class.
Ambiguity resolution using scope resolution operator and
Virtual base class

Ambiguity Resolution:
When a derived class inherits from multiple base classes and those base
classes have members with the same name, ambiguity arises.
To specify which base class's member you want to access, use the scope
resolution operator.

#include <iostream>

class Base1 {

public:

void print() {

std::cout << "Base1 print" << std::endl;

};

class Base2 {

public:

void print() {

std::cout << "Base2 print" << std::endl;

};

class Derived : public Base1, public Base2 {

public:

void print() {

Base1::print(); // Call Base1's print function

Base2::print(); // Call Base2's print function

};

int main() {

Derived d;

d.print();

return 0;
In C++ inheritance, ambiguity resolution using the scope resolution operator (::)
and virtual base classes are both techniques used to address situations where a
derived class inherits from multiple base classes that have members with the
same name, allowing you to explicitly specify which base class member you
want to access when needed, while virtual base classes ensure that only a single
instance of a common base class exists in a multiple inheritance hierarchy,
effectively preventing ambiguity in the "diamond problem" scenario.

Explanation:

Scope Resolution Operator (::):


Function: When a derived class inherits from multiple base classes with
members of the same name, the scope resolution operator is used to explicitly
qualify which base class's member you want to access

class Base1 { public: void print() { std::cout <<


"Base1"; } };

class Base2 { public: void print() { std::cout <<


"Base2"; } };

class Derived : public Base1, public Base2 {

public:

void callPrint() {

Base1::print(); // Accessing Base1's print


function explicitly

Base2::print(); // Accessing Base2's print


function explicitly

}
};
Virtual Base Class:
Function: By declaring a base class as "virtual" in the inheritance hierarchy, you
ensure that only one instance of that class exists in the derived class, even when
multiple inheritance paths lead to the same base class.

Resolving the Diamond Problem: This is particularly useful in the "diamond


problem" where a class inherits from two classes that both inherit from a
common base class, preventing ambiguity about which base class instance to
use.

Example:

class Base { public: void print() { std::cout << "Base"; } };

class Derived1 : public virtual Base { }; // Virtual inheritance

class Derived2 : public virtual Base { };

class FinalDerived : public Derived1, public Derived2 {

public:

void callPrint() {

Base::print(); // Accesses the single Base instance

};

Key Points:

When to use scope resolution operator:


When you need to access a specific base class member explicitly in a multiple inheritance
scenario where ambiguity might occur.

When to use virtual base class:


When you want to ensure that only a single instance of a common base class exists in a
complex inheritance hierarchy, particularly in the "diamond problem" situation.

Method Overriding:-
 the process of implementing super class method in the sub class method
called method overriding.

Since function calling is mode under the function body thus it is named function or method
overriding.
 Calling of function is done with the help of class name and scope
resolution operator.
 Class name:: function name();
 Sub class can be written for three reasons.
1) To add new functionality.
2) To overwrite the existing functionality.
3) To inherit the existing functionality.
 When you overriding super class method in sub class you need to follow the
following rules.
1) Sub class method is same as super class method name.
2) Sub class method return type must be same as super method parame
3) Sub class method parameter is same as super class method return type-:
Ex-:
#include<iostream.h>
#include<conio.h>
class student{
protected:
char sname[20],course[20];
int roll;
public:
void getdata(){
cout<<"Enter name”:-
cin>>sname;
cout<<"Enter course-:”
cin>>course ;
cout << “ enter rollno:-";
cin>>roll;
}
Void show(){
cout<<endl<<"student name:- "<<sname;
cout<<endl<<"Roll no:- "<<roll;
cout<<endl<<"course:- "<<course;
};
class Hostal:public student{
int hostalno, fee;
public:
void getdata(){
student::getdata();
cout<<"Enter Hostal number:- ";
cin>>hostalno;
cout<<"Enter course fee:- ";
cin>>fee;
}
void show(){
student::show();
cout<<endl<<"hostal number:- "<<hostalno;
cout<<endl<<"course fee:- "<<fee;
}
};
int main(){
Hostal h;
h.getdata();
h.show();
getch();
return 0;
}

Inheritance with constructors:-

 Since we know that constructor is a group of member functions mainly used for
initial id purpose for the data members
 In the case of communities there is a criteria behind the use of the structure That in
base class you constructed then it become necessary that each derived class also
used otherwise constructor is not used
 Here for use of constructor in case of inheritance is totally depend upon the base
class
 Points
 When you not writing any corrupted inside the class then default concept will be
inserted by the compiler
 When you have any arguments constructor inside the class then default constructor
will not be inserted for the compiler
 When you create sub class of this object then sub class constructor and super class
constructor will be called and initialising sub class variable to initialise super class
variable
 When you create super class object then sub class constructor will be called an super
class variable and not initialization subclass variable.

Ex-:
#include<iostream.h>
#include<conio.h>
Class demo1{
Protected:
Int n1,n2;
public:
demo1(int a, int b){
n1=a;
n2=b;
}
void show(){
cout<<endl<<"value of n1:- "<<n1;
cout<<endl<<"value of n2:- "<<n2;
{
};
class demo2:public demo1{ int n3,n4;
public:
demo2(int a, int b,int c,int d):demo1(a,b){ n3=c; n4=d; }
void show(){
demo1::show();
cout<<endl<<"value of n3:- "<<n3;
cout<<endl<<"value of n4:- "<<n4;
}
};
int main(){
demo2 d(10,20,30,40);
demo1 d2(50,60);
d2.show();
d.show();
getch();
return 0;
}

Nested class-:
Nested classes in C++ provide a way to encapsulate a class within another class, creating a
hierarchical relationship between them. Here's a breakdown of nested classes and their
inheritance in C++:
Nested Classes:
 A nested class is a class defined within the scope of another class, known as the
enclosing class.
 The nested class has access to all members (private, protected, and public) of the
enclosing class, but the enclosing class doesn't have direct access to the private
members of the nested class.
 Nested classes can be useful for encapsulating functionality that is closely related to
the enclosing class, improving code organization and readability.

Example of a Nested Class:


class Outer {
public:
int x;

class Inner {
public:
void printX() {
std::cout << x << std::endl; // Accesses Outer::x
}
};
};

int main() {
Outer outer;
outer.x = 10;

Outer::Inner inner;
inner.printX(); // Output: 10
return 0;
}

Inheritance with Nested Classes:


 A nested class can inherit from another class, just like a regular class.
 The inheritance rules apply in the same way, including access specifiers (public,
protected, and private).

Example of Inheritance with Nested Classes:

class Outer {
public:
int x;

class Inner {
public:
virtual void print() {
std::cout << "Inner\n";
}
};
};
class Derived : public Outer::Inner {
public:
void print() override {
std::cout << "Derived\n";
}
};

int main() {
Derived derived;
derived.print(); // Output: Derived
return 0;
}
Important Points to Remember:
 Access Control:
The nested class has access to the enclosing class's members, but the enclosing class doesn't
have direct access to the nested class's private members.
 Scope:
The name of the nested class is within the scope of the enclosing class.
 Instantiation:
To use the nested class, you need to create an object of the enclosing class first.
 Inheritance:
A nested class can inherit from other classes, and the same inheritance rules apply as with
regular classes.
Benefits of Using Nested Classes and Inheritance:
 Encapsulation: Improves code organization by grouping related classes together.
 Code Reusability: Facilitates code reusability through inheritance.
 Readability: Makes code more readable and maintainable.

ACCESS MODES
Access modifiers are used to implement an important aspect of Object-Oriented Programming known
as Data Hiding. Consider a real-life example:
The Research and Analysis Wing (R&AW), having 10 core members, has come into possession of
sensitive confidential information regarding national security. Now we can correlate these core
members to data members or member functions of a class, which in turn can be correlated to the R&A
Wing. These 10 members can directly access the confidential information from their wing (the class),
but anyone apart from these 10 members can’t access this information directly, i.e., outside functions
other than those prevalent in the class itself can’t access the information (that is not entitled to them)
without having either assigned privileges (such as those possessed by a friend class or an inherited
class, as will be seen in this article ahead) or access to one of these 10 members who is allowed direct
access to the confidential information (similar to how private members of a class can be accessed in
the outside world through public member functions of the class that have direct access to private
members). This is what data hiding is in practice.
Access Modifiers or Access Specifiers in a class are used to assign the accessibility to the class
members, i.e., they set some restrictions on the class members so that they can’t be directly accessed
by the outside functions.
There are 3 types of access modifiers available in C++:
1. Public
2. Private
3. Protected
Note: If we do not specify any access modifiers for the members inside the class, then by default the
access modifier for the members will be Private. Understanding how to use public, private, and
protected access modifiers is essential. The C++ Course provides detailed explanations and examples
to help you implement these concepts effectively.
Let us now look at each one of these access modifiers in detail:
1. Public: All the class members declared under the public specifier will be available to everyone.
The data members and member functions declared as public can be accessed by other classes and
functions too. The public members of a class can be accessed from anywhere in the program using the
direct member access operator (.) with the object of that class.
Example:
CPP
// C++ program to demonstrate public
// access modifier

#include<iostream>
using namespace std;

// class definition
class Circle
{
public:
double radius;

double compute_area()
{
return 3.14*radius*radius;
}

};

// main function
int main()
{
Circle obj;
// accessing public datamember outside class
obj.radius = 5.5;

cout << "Radius is: " << obj.radius << "\n";


cout << "Area is: " << obj.compute_area();
return 0;
}
Output:
Radius is: 5.5
Area is: 94.985
In the above program, the data member radius is declared as public so it could be accessed outside the
class and thus was allowed access from inside main().
2. Private: The class members declared as private can be accessed only by the member functions
inside the class. They are not allowed to be accessed directly by any object or function outside the
class. Only the member functions or the friend functions/ friend class are allowed to access the private
data members of the class.
Example:
CPP
// C++ program to demonstrate private
// access modifier

#include<iostream>
using namespace std;

class Circle
{
// private data member
private:
double radius;

// public member function


public:
double compute_area()
{ // member function can access private
// data member radius
return 3.14*radius*radius;
}

};

// main function
int main()
{
// creating object of the class
Circle obj;

// trying to access private data member


// directly outside the class
obj.radius = 1.5;

cout << "Area is:" << obj.compute_area();


return 0;
}

Output:
In function 'int main()':
11:16: error: 'double Circle::radius' is private
double radius;
^
31:9: error: within this context
obj.radius = 1.5;
^
The output of the above program is a compile time error because we are not allowed to access the
private data members of a class directly from outside the class. Yet an access to obj.radius is
attempted, but radius being a private data member, we obtained the above compilation error.
However, we can access the private data members of a class indirectly using the public member
functions of the class.
Example:
CPP
// C++ program to demonstrate private
// access modifier

#include<iostream>
using namespace std;

class Circle
{
// private data member
private:
double radius;

// public member function


public:
void compute_area(double r)
{ // member function can access private
// data member radius
radius = r;

double area = 3.14*radius*radius;

cout << "Radius is: " << radius << endl;


cout << "Area is: " << area;
}

};

// main function
int main()
{
// creating object of the class
Circle obj;
// trying to access private data member
// directly outside the class
obj.compute_area(1.5);

return 0;
}
Output:
Radius is: 1.5
Area is: 7.065
3. Protected: The protected access modifier is similar to the private access modifier in the sense that
it can’t be accessed outside of its class unless with the help of a friend class. The difference is that the
class members declared as Protected can be accessed by any subclass (derived class) of that class as
well.
Note: This access through inheritance can alter the access modifier of the elements of base class in
derived class depending on the mode of Inheritance.
Example:
CPP
// C++ program to demonstrate
// protected access modifier
#include <bits/stdc++.h>
using namespace std;

// base class
class Parent
{
// protected data members
protected:
int id_protected;

};

// sub class or derived class from public base class


class Child : public Parent
{
public:
void setId(int id)
{

// Child class is able to access the inherited


// protected data members of base class

id_protected = id;

void displayId()
{
cout << "id_protected is: " << id_protected << endl;
}
};

// main function
int main() {

Child obj1;

// member function of the derived class can


// access the protected data members of the base class

obj1.setId(81);
obj1.displayId();
return 0;
}
Output:
id_protected is: 81

Difference between Private and Protected

Private Protected

The class members declared as private


Protected access modifier is similar to that of private
can be accessed only by the functions
access modifiers.
inside the class.

Private members keep implementation Protected members enhanced access for derived
details in a program. classes.

Only the member functions or the friend The class member declared as Protected are
functions are allowed to access the private inaccessible outside the class but they can be
data members of a class. accessed by any subclass(derived class) of that class.

Private members are inherited by derived


classes but are not directly accessible in Protected member are i
the derived classes..

Function Overriding in C++:


A function is a block of statements that together performs a specific task by taking some input and
producing a particular output. Function overriding in C++ is termed as the redefinition of base class
function in its derived class with the same signature i.e. return type and parameters. It can be of both
type: Compile Time and Runtime Polymorphism.
What is Function Overriding in C++?
Function overriding is a type of polymorphism in which we redefine the member function of a class
which it inherited from its base class. The function signature remains same but the working of the
function is altered to meet the needs of the derived class. So, when we call the function using its name
for the parent object, the parent class function is executed. But when we call the function using the
child object, the child class version will be executed.
Real-Life Example of Function Overriding
The best Real-life example of this concept is the Constitution of India. India took the political code,
structure, procedures, powers, and duties of government institutions and set out fundamental rights,
directive principles, and the duties of citizens of other countries and implemented them on its own;
making it the biggest constitution in the world.
Another Development real-life example could be the relationship between RBI(The Reserve Bank of
India) and Other state banks like SBI, PNB, ICICI, etc. Where the RBI passes the same regulatory
function and others follow it as it is.

Function Overriding
Types of Function Overriding in C++
Unlike other languages such as Java where function overriding is strictly done at compile time, C++
supports two types of function overriding:
 Compile Time Overriding
 Runtime Function Overriding
Compile Time Function Overriding
In compile time function overriding, the function call and the definition is binded at the compilation
of the program. Due to this, it is also called early binding or static binding.
Syntax
class Parent {
access_modifier :

// overridden function
return_type name_of_the_function() {}
};

class child : public Parent {


access_modifier :

// overriding function
return_type name_of_the_function() {}
};
Example of Compile Time Function Overriding
C++
// C++ program to demonstrate compile time function overriding

#include <iostream>
using namespace std;

class Parent {
public:
void GeeksforGeeks_Print()
{
cout << "Base Function" << endl;
}
};

class Child : public Parent {


public:
void GeeksforGeeks_Print()
{
cout << "Derived Function" << endl;
}
};

int main()
{
Child Child_Derived;
Child_Derived.GeeksforGeeks_Print();
return 0;
}

Output
Derived Function
Runtime Function Overriding using Virtual Function
Unlike other languages like Java, the function overriding in C++ can be performed at both compile
time and runtime. In all the above examples, the call to the overridden function is resolved during
compile time. It is also called early binding where the function call is binded to its definition during
compilation.
Function overriding can also be performed at the runtime, which means that function call will be
binded to its definition during runtime (also known as late binding or dynamic binding). This can be
done with the help of virtual functions.
Syntax
class Base {
public:
virtual func()
{
// definition
}
};

class Derived : public Base {


public:
func() override
{
// new definition
}
};

Here, override keyword tells the compiler that the given overridden function should be declared as
virtual in the parent class. It is a kind of double check as the program can compile without errors even
if the function is not virtual. But then, it will be compile time polymorphism and we won’t get the
desired behaviour of the function overriding.
Example of Runtime Function Overriding using Virtual Function
C++
// C++ Program to illustrate how to implement runtime
// function overriding using virtual function
#include <iostream>
using namespace std;
class Base {
public:
// Declare the function as virtual to allow overriding
// in derived classes
virtual void display()
{
cout << "Display method of Base class" << endl;
}

// Virtual destructor to ensure proper cleanup of


// derived class objects
virtual ~Base() {}
};

class Derived : public Base {


public:
// Override the display method
void display() override
{
cout << "Display method of Derived class" << endl;
}
};

int main()
{
Base* basePtr;
Derived derivedObj;

// Point base class pointer to derived class object


basePtr = &derivedObj;
// Call the display function
// This will call the display method of the Derived
// class due to the virtual function mechanism
basePtr->display();

return 0;
}

Output
Display method of Derived class
Advantages of Runtime Function Overriding
The following are the main advantages of function overriding:
 Methods are selected at runtime based on object type.
 Common interfaces and implementations can be reused as we only need to implement the
interface for base class.
 Changes in base classes automatically affect derived classes.
 Facilitates the implementation of design patterns different design patterns.
 Client code interacts with base class interface, not specific implementations reducing the
coupling.
Limitations of Runtime Function Overriding
While runtime function overriding provides numerous advantages, it also comes with certain
limitations:
 Virtual function calls are generally slower than non-virtual function calls due to the
indirection involved in the virtual table lookup.
 Implementing and maintaining polymorphic code can be more complex compared to simpler
non-polymorphic code.
 Virtual tables and virtual pointers add to the memory overhead, especially in large systems
with many classes.
 Errors related to function overriding (e.g., incorrect signatures) might only be detected at
runtime, leading to potential bugs.
Examples of Function Overriding in C++
Example 1: C++ Program to Call Overridden Function From Derived Class
C++
// C++ program to demonstrate function overriding
// by calling the overridden function
// of a member function from the child class

#include <iostream>
using namespace std;

class Parent {
public:
void GeeksforGeeks_Print()
{
cout << "Base Function" << endl;
}
};

class Child : public Parent {


public:
void GeeksforGeeks_Print()
{
cout << "Derived Function" << endl;

// call of original function


Parent::GeeksforGeeks_Print();
}
};

int main()
{
Child Child_Derived;
Child_Derived.GeeksforGeeks_Print();
return 0;
}

Output
Derived Function
Base Function

The output of Call Overridden Function From Derived Class


Example 2: C++ Program to Call Overridden Function Using Pointer
C++
// C++ program to access overridden function using pointer
// of Base type that points to an object of Derived class
#include <iostream>
using namespace std;
class Parent {
public:
void GeeksforGeeks()
{
cout << "Base Function" << endl;
}
};

class Child : public Parent {


public:
void GeeksforGeeks()
{
cout << "Derived Function" << endl;
}
};

int main()
{
Child Child_Derived;

// pointer of Parent type that points to derived1


Parent* ptr = &Child_Derived;

// call function of Base class using ptr


ptr->GeeksforGeeks();

return 0;
}

Output
Base Function
Example 3: C++ Program to Access of Overridden Function using Child Class Object
C++
// C++ program to access overridden function
// in main() using the scope resolution operator ::

#include <iostream>
using namespace std;

class Parent {
public:
void GeeksforGeeks()
{
cout << "Base Function" << endl;
}
};

class Child : public Parent {


public:
void GeeksforGeeks()
{
cout << "Derived Function" << endl;
}
};

int main()
{
Child Child_Derived;
Child_Derived.GeeksforGeeks();

// access GeeksforGeeks() function of the Base class


Child_Derived.Parent::GeeksforGeeks();
return 0;
}

Output
Derived Function
Base Function

Access of Overridden Function to the Base Class

Function Overloading Vs Function Overriding

Function Overloading Function Overriding

It falls under Compile-Time polymorphism It can be both Compile Time or Runtime


Function Overloading Function Overriding

Polymorphism

A function can be overloaded multiple times as A function cannot be overridden multiple times
it is resolved at Compile time as it is resolved at Run time

Can be executed without inheritance Cannot be executed without inheritance

They are in the same scope They are of different scopes.

You might also like