0% found this document useful (0 votes)
7 views48 pages

Module 4 - Oops

Uploaded by

ankithavv13
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views48 pages

Module 4 - Oops

Uploaded by

ankithavv13
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 48

Module 4 - Virtual function

• When you declare a function as virtual in a base class and then


override it in derived classes, the functions share the same name but
can perform different operations based on the specific class
implementation.
• Here are some examples where virtual functions could be used in a
base class and overridden in derived classes:
• Employee as Base Class
• Derived Classes: Manager, Engineer
• Virtual Functions: calculateSalary(), displayDetails()
• Usage: Each derived class can override calculateSalary() to compute
salary based on specific rules (e.g., bonus for managers, overtime for
engineers).
• displayDetails() can be overridden to show additional information
specific to each role.
• Shape as Base Class
• Derived Classes: Circle, Square, Triangle
• Virtual Functions: calculateArea(), calculatePerimeter(), draw()
• Usage: Each derived class implements its own version of calculateArea()
and calculatePerimeter() based on its shape properties (e.g., radius for
circle, side length for square).
• draw() can be overridden to visually represent each shape.
• Bank Account as Base Class
• Derived Classes: SavingsAccount, CheckingAccount,
InvestmentAccount
• Virtual Functions: deposit(), withdraw(), calculateInterest()
• Usage: Each derived class can override calculateInterest() to compute
interest based on its specific type (e.g., fixed rate for savings, variable
rate for investment). deposit() and withdraw() can have specific rules
or fees for each account type.
• When using virtual functions in C++, it's generally recommended to
call them through pointers (or references) to the base class rather
than directly through objects of the derived class.

• There are two ways of calling virtual functions


• 1. calling virtual functions through pointers
• 2. calling virtual functions through base class reference
Calling virtual function through
pointer
Syntax is
Base_class *pointer
Pointer = &objectname(base/derive)
Pointerfunction_name
• #include <iostream>
• // Base class
• class Employee
• {
• public:
• virtual void calculateSalary()
• {
• cout << "Calculating salary for employee." ;
• }
• };
• // Derived class for Manager
• class Manager : public Employee
•{
• public:
• void calculateSalary()
•{
• cout << "Calculating salary for manager: Base salary + Bonuses." ;
•}
• };
• // Derived class for Engineer
• class Engineer : public Employee
•{
• public:
• void calculateSalary()
•{
• cout << "Calculating salary for engineer: Base salary + Overtime." ;
• }
• };
int main()
{
Employee *p;
Employee emp;
manager emp1;
Engineer emp2;

P=&emp;
P calculateSalary();

P=&emp1;
p->calculateSalary(); // Calls Manager's calculateSalary()
• P=&emp2;
• p->calculateSalary(); // Calls Engineer's calculateSalary()
•}

• Output With Virtual Functions:


• Calculating salary for manager: Base salary + Bonuses.
• Calculating salary for engineer: Base salary + Overtime.
Calling virtual function through
reference (base class reference)
• Syntax is
If the
base class is b,
derived_1 class object is d1 and
derived_2 class object is d2
then pass them to a reference function(ref_func) as
ref_func(b),
ref_func(d1),
ref_func(d2)
Body of ref_func is
Void ref_func(base &r)
{
r.vfunc();
}
#include <iostream>
// Base class
class Employee
{
public:
virtual void calculateSalary()
{
cout << "Calculating salary for employee." ;
}
};
// Derived class for Manager
class Manager : public Employee
{
public:
void calculateSalary()
{
cout << "Calculating salary for manager: Base salary + Bonuses." ;
}
};
// Derived class for Engineer
class Engineer : public Employee
{
public:
void calculateSalary()
{
cout << "Calculating salary for engineer: Base salary + Overtime." ;
}
};
Void ref_func(base &r)
{
r.calculateSalary();
}

int main()
{
Employee emp;
manager emp1;
Engineer emp2;
ref_func(emp);
ref_func(emp1);
ref_func(emp2);
}
The virtual attribute is inherited
• When a virtual function is inherited, its virtual nature is also inherited.
This means that when a derived class that has inherited a virtual
function is itself used as a base class for another derived class, the
virtual function is still be overridden.
• Put differently, no matter how many times a virtual function is
inherited , it remains virtual.
Class base
{
Public:
Virtual void vfunc()
{
Cout<<“this is base’s vfunc()”;
}
};
Class derived1 : public base
{
Public:
void vfunc()
{
Cout<<“this is derived1’s vfunc()”;
}
};
Class derived2 : public derived1
{
Public:
void vfunc() //vfunc is still virtual
{
Cout<<“this is derived2’s vfunc()”;
}
};
Void main()
{
Base *p,b;
Derived d1;
Derived d2;

P=&b;
Pvfunc();
p=&d1;
pvfunc();

p=&d2;
pvfunc();

Output:
This is base’s vfunc()
This is derived1’s vfunc()
This is derived2’s vfunc()

In this case, derived2 inherits derived1 rather than base, but vfunc() is still virtual
Virtual functions are
hierarchical
• When a function is declared as virtual by a base class, it may be
overridden by a derived class.
• However the function does not have to be overridden.
• When a derived class fails to override a virtual function, then when an
object of that derived class accesses that function, the function
defined by the base class is used.
Class base
{
Public:
Virtual void vfunc()
{
Cout<<“this is base’s vfunc()”;
}
};
Class derived1 : public base
{
Public:
void vfunc()
{
Cout<<“this is derived1’s vfunc()”;
}
};
Class derived2 : public base
{
Public:
//vfunc is not overridden by derived2, base’s vfunc is used here
};

Void main()
{
Base *p,b;
Derived d1;
Derived d2;

P=&b;
Pvfunc(); //access base’s vfunc
p=&d1;
pvfunc(); //access derived1’s vfunc

p=&d2;
pvfunc(); // uses base’s vfunc

}
• Because derived2 does not override vfunc(), the function defined by
base is used when vfunc() is referenced relative to objects of type
derived2.

• This means that when a derived class fails to override a virtual


function, the first redefinition found in reverse order of derivation is
used.

• In the following program derived2 is derived from derived1, which is


derived from base. But derived2 does not override vfunc. Here
relative to derived2, the closest version of vfunc is in derived1.
Therefore derived1’s vfunc (derived1::vfunc) is used when an object of
derived2 attempts to call vfunc().
Class base
{
Public:
Virtual void vfunc()
{
Cout<<“this is base’s vfunc()”;
}
};
Class derived1 : public base
{
Public:
void vfunc()
{
Cout<<“this is derived1’s vfunc()”;
}
};
Class derived2 : public derived1
{
Public:
/*vfunc is not overridden by derived2.
In this case, since derived2 is derived from derived1, derived1’s vfunc() is
used.*/
};
Void main()
{
Base *p,b;
Derived d1;
Derived d2;

P=&b;
Pvfunc(); // access base’s vfunc()
p=&d1;
pvfunc(); //access derived1’s vfunc()

p=&d2;
pvfunc(); // uses derived1’s vfunc()

}
Example for pure virtual function
Class base
{
Public:
Virtual void vfunc()=0;
};

Class derived1 : public base


{
Public:
void vfunc()
{
Cout<<“this is derived1’s vfunc()”;
}
};
Class derived2 : public base
{
Public:
void vfunc()
{
Cout<<“this is derived1’s vfunc()”;
}
};

Void main()
{
Base *p,b;
Derived d1;
Derived d2;

P=&b;
Pvfunc();
p=&d1;
pvfunc();

p=&d2;
pvfunc();

}
Write example of pure virtual function here…
Using Virtual Function
• One of the central aspect of using virtual function to get - “one
interface, multiple methods”.
• This is known as polymorphism. (occurring in different forms)
• In base class you create and define everything you can that relates to
the general case. The derived classes fills in the specific details.
• One simple example is as follows
• The base class name is convert which has two variables i.e val1 and val2.
val1 which hold the initial value and val2 holds the converted value.
• The convert class has compute as virtual function which can be used in
derived classes to compute the converted value.
Class convert
{
Public:
Double val1;
Double val2;
Virtual void compute()=0;
}
Class l_to_g : public convert // litre to gallons : 1 gallon = 3.78541 litres
{
Void compute()
{
Val2=val1/3.78541;
Cout<<val1<<“liters is =“<<val2<<“gallons”;
}
};
Class f_to_c : public Celsius
{
Public:
Void compute()
{
Val2=(val1-32)/1.8;
Cout<<val1<<“fahrenheit is =“<<val2<<“celsius”;
}
};
Void main()
{
Convert *p;
double val1;

cout << "Enter value in liters for conversion to gallons: ";


cin >> val1;

L_to_g lgob;
lgob.val1 = val1;

p = &lgob;
p->compute();
cout << "Enter value in fahrenheit for conversion to celsius: ";
cin >> val1;

F_to_c fcob;
fcob.val1 = val1;

p = &fcob;
p->compute();
}
• One of the benefits of derived classes and virtual function is that
handling a new case is a very easy matter.
• For example, assuming the preceding program, you can add a
conversion from feet to meters by including this class:
• Class f_to_m : public convert
•{
• Public:
• Void compute()
•{
• Val2=val1/3.28;
•}
• };
Early binding vs Late binding
• Early binding refers to events that occur at compile time.
• In essence, early binding occurs when all information needed to call a function is known at compile time. (Put differently,
early binding means that an object and a function call are bound during compilation.)
• Examples of early binding include normal function calls (including standard library functions), overloaded function calls, and
overloaded operators.
• The main advantage to early binding is efficiency. Because all information necessary to call a function is determined at
compile time, these types of function calls are very fast. The opposite of early binding is late binding.
• As it relates to C++, late binding refers to function calls that are not resolved until run time. Virtual functions are used to
achieve late binding.
• As you know, when access is via a base pointer or reference, the virtual function actually called is determined by the type of
object pointed to by pointer.
• Because in most cases this cannot be determined at the compile time , the object and the function are not linked until run
time.
• The main advantage to late binding is flexibility. Unlike early binding, late binding allows you to create programs that can
respond to events occurring while the program executes without having to create a large amount of "contingency code.“
• Keep in mind that because a function call is not resolved until run time, late binding can make for somewhat slower
execution times.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy