0% found this document useful (0 votes)
22 views42 pages

Unit 3-4

Virtual functions allow polymorphism by overriding functions in derived classes. When called via a base class pointer, the version of the function that is called is determined by the actual object type at runtime rather than by the type of the pointer at compile time. Virtual functions are useful for runtime polymorphism but have some performance overhead and complexity compared to non-virtual functions.

Uploaded by

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

Unit 3-4

Virtual functions allow polymorphism by overriding functions in derived classes. When called via a base class pointer, the version of the function that is called is determined by the actual object type at runtime rather than by the type of the pointer at compile time. Virtual functions are useful for runtime polymorphism but have some performance overhead and complexity compared to non-virtual functions.

Uploaded by

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

VIRTUAL FUNCTIONS

• Polymorphism refers to the property by which objects belonging to different


classes are able to respond to the same message, but different forms.
• An essential requirement of polymorphism is therefore the ability to refer to
objects without any regard to their classes.
• When we use the same function name in both the base and derived classes,
the function in the bas class is declared as virtual using the keyword virtual
preceding its normal declaration.
• When a function is made virtual, C++ determines which function to use at
runtime based on the type of object pointed to by the base pointer, rather than
the type of the pointer.
• Thus, by making the base pointer to point to different objects, we can execute
different versions of the virtual function.

Rakesh Sharma
#include<iostream.h> {
#include<conio.h> cout << "display from drive"<<endl;
class base }
{ void show()
public: {
void display() cout<<" show function of drive"<<endl;
{ }
cout << "display from base"<<endl; };
} void main()
void show() {
{ clrscr();
cout<<" show function of base"<<endl; drive ob;
} ob.display();
}; ob.show();
class drive: public base getch();
{ }

public:
void display()
Rakesh Sharma
Output:
display from drive
show function of drive

Rakesh Sharma
#include<iostream.h> }
#include<conio.h> };
class base void main()
{ {
public: clrscr();
void display() base b ;
{ drive d;
cout << "display from base"<<endl; base *ptr;
}
void show() ptr = &b;
{ ptr->display() ; // display from base
cout<<" show function of base"<<endl; ptr->show(); // show function of base
}
}; ptr = &d;
class drive: public base ptr->display() ; // display from base
{ ptr->show(); //show function of base
public: getch();
void display() }
{
cout << "display from drive"<<endl;
}
void show()
Rakesh Sharma
{
cout<<" show function of drive"<<endl;
#include<iostream.h> {
#include<conio.h> cout<<" show function of drive"<<endl;
class base }
{ };
public: void main()
void display() {
{ clrscr();
cout << "display from base"<<endl; base b;
} drive d;
virtual void show() base *ptr;
{
cout<<" show function of base"<<endl; ptr = &b;
} ptr->display() ; // display from base
}; ptr->show(); // show function of base
class drive: public base
{ ptr = &d;
public: ptr->display() ; // display from base
void display() ptr->show(); //show function of drive
{ getch();
cout << "display from drive"<<endl; }
}
void show() Rakesh Sharma
Explanation:

• Runtime polymorphism is achieved only through a pointer (or


reference) of the base class type. Also, a base class pointer can point
to the objects of the base class as well as to the objects of the derived
class. In the above code, the base class pointer ‘ptr’ contains the
address of object ‘d’ of the derived class.

• Late binding (Runtime) is done in accordance with the content of the


pointer (i.e. location pointed to by pointer) and Early binding (Compile-
time) is done according to the type of pointer since the print() function
is declared with the virtual keyword so it will be bound at runtime
(output is print derived class as the pointer is pointing to object of
derived class) and show() is non-virtual so it will be bound during
compile time (output is show base class as the pointer is of base type).

Rakesh Sharma
Limitations of Virtual Functions

• Slower: The function call takes slightly longer due to the virtual
mechanism and makes it more difficult for the compiler to optimize
because it does not know exactly which function is going to be called
at compile time.

• Difficult to Debug: In a complex system, virtual functions can make it


a little more difficult to figure out where a function is being called
from.

Rakesh Sharma
#include<iostream.h> }
class Base };
{
public: void main( )
void display() {
{ Base b;
cout<<”Display Base”; Derived d;
} Base *ptr;
virtual void show() cout<<”ptr points to Base”;
{ ptr = &b;
cout<<”Show Base”; ptr->display(); //calls Base
Rakesh Sharma
} ptr->show(); //calls Base
}; cout<<”ptr points to derived”;
class Derived : public Base ptr=&d;
{ ptr->display(); //calls Base
public: ptr->show(); //class
Derived
void display()
}
{
cout<<”Display Derived”;
}
void show( )
{
cout<<”show derived”;
Output:

ptr points to Base


Display Base
Show Base
ptr points to Derived
Display Base
Show Derived

Rakesh Sharma
Rules For Virtual Functions:
When virtual functions are created for implementing late binding, observe some basic rules that satisfy the compiler
requirements.
1. The virtual functions must be members of some class.
2. They cannot be static members.
3. They are accessed by using object pointers.
4. A virtual function can be a friend of another class.
5. A virtual function in a base class must be defined, even though it may not be used.
6. The prototypes of the base class version of a virtual function and all the derived class versions must be
identical. C++ considers them as overloaded functions, and the virtual function mechanism is ignored.
7. We cannot have virtual constructors, but we can have virtual destructors.
8. While a base pointer points to any type of the derived object, the reverse is not true. i.e. we cannot
use a pointer to a derived class to access an object of the base class type.
9. When a base pointer points to a derived class, incrementing or decrementing it will not make it to
point to the next object of the derived class. It is incremented or decremented only relative to its
base type. Therefore we should not use this method to move the pointer to the next object.
Rakesh Sharma
10. If a virtual function is defined in the base class, it need not be necessarily redefined in the
derived class. In such cases, calls will invoke the base function.
DYNAMIC MEMORY ALLOCATION & DEALLOCATION (new & delete)
• C++ supports these functions, it defines two unary operators new and delete that perform the task of allocating and
deallocating the memory in a better and easier way.
• A object can be created by using new, and destroyed by using delete.
• A data object created inside a block with new, will remain in existence until it is explicitly destroyed
by using delete.
new operator:-
• new operator can be used to create objects of any type .Hence new operator allocates sufficient memory to hold
data of objects and it returns address of the allocated memory.
• Syntax:
pointer-variable = new data-type;
Ex: int *p = new int;
int *p = new int;
*p = 45;

float *q = new float;


*q = 9.8;

Rakesh Sharma
• To create memory space for arrays:
• pointer-variable = new data-type[size];

Ex: int *p = new int[10];

The following are the advantages of the new operator over malloc() function:
• It does not use the sizeof() operator as it automatically computes the size of the
data object.
• It automatically returns the correct data type pointer, so it does not need to use
the typecasting.
• Like other operators, the new and delete operator can also be overloaded.
• It also allows you to initialize the data object while creating the memory space
for the object.

Rakesh Sharma
Program using new operator:
#include <iostream>
void main()
{
int *ptr;
// integer pointer variable declaration
ptr=new int;
// allocating memory to the pointer variable ptr.
cout << "Enter the number : " << endl;
cin >>*ptr;
cout << "Entered number is " <<*ptr<< endl;
}
• Output:
Rakesh Sharma
delete operator:

• If the variable or object is no longer required or needed is destroyed by


“delete” operator, there by some amount of memory is released for future
purpose.
Synatx:
delete pointer-variable;

Eg: delete p;
If we want to free a dynamically allocated

array: delete [size] pointer-variable;

Rakesh Sharma
Program Using new and delete operator:
#include <iostream> }
using namespace std cout<<"\nThe elements that you have
void main() entered are :";
{ for(int i=0;i<size;i++)
int size; {
int *arr = new int[size]; // cout<<arr[i]<<",";
creating an array }
cout<<"Enter the size of the array : "; delete arr; // deleting an existing
cin >> size; // array.
cout<<"\nEnter the element : ";
for(int i=0;i<size;i++) // for loop }
{ Output:
cin>>arr[i];
Rakesh Sharma
Program: write a program to find sum of list of
integers
#include<iostream> for( int i=0;i<n;i++)
int main() {
{ s=s+p[i];
int n,*p; }
cout<<"Enter array size:"; cout<<"Sum of array elements is“<<endl;
cin>>n; cout<<s;
p=new int[n]; delete [ ]p;
return 0;
cout<<"Enter list of integers"<<endl; }
for(int i=0;i<n;i++)
Rakesh Sharma
{ Output:
cin>>p[i]; Enter list of integers
} 12345
Sum of array elements is
int s=0; 15
Data File Handling In C++
• File handling is used to store data permanently in a computer. Using
file handling we can store our data in secondary memory (Hard disk).

How to achieve the File Handling:

For achieving file handling we need to follow the following steps:-

STEP 1- Naming a file


STEP 2- Opening a file
STEP 3- Writing data into the file
STEP 4- Reading data from the file
STEP 5- Closing a file.

Rakesh Sharma
Data File Handling In C++
File: - A file is collection of data or information that has a name, called the filename. Files are stored in
secondary storage devices such as pen drive and hard disks. The information / data stored under a specific
name on a storage device, is called a file.

Stream: - It refers to a sequence of bytes.


We give input to the executing program and the execution program gives back the output. The
sequence of bytes given as input to the executing program and the sequence of bytes that comes
as output from the executing program are called stream. In other words, streams are nothing but
the flow of data in a sequence

Text file: -
It is a file that stores information in ASCII characters. In text files, each line of text is terminated with a
special character known as EOL (End of Line) character or delimiter character. When this EOL character is
read or written, certain internal translations take place.

Binary file:-
It is a file that contains information in the same format as it is held in memory. In binary files, no delimiters
are used for a line and no translations occur here.
Rakesh Sharma
C++ Files and Streams
• In C++ programming we are using the iostream standard library, it
provides cin and cout methods for reading from input and writing to
output respectively.

• To
Dataread
Type and write from a file we Description
are using the standard C++ library
called fstream. Let us see the data types define in fstream library is:
fstream It is used to create files, write information to files, and
read information from files.

ifstream It is used to read information from files.

ofstream It is used to create files and write information to the


files.

Rakesh Sharma
ifstream:-
• This class provides input operations.
• It contains open() function with default input mode.
• Inherits the functions get(), getline(), read(), seekg() and tellg()
functions from the istream.

ofstream:-
• This class provides output operations.
• It contains open() function with default output mode.
• Inherits the functions put(), write(), seekp() and tellp() functions from
the ostream.

fstream:-
• This class provides support for simultaneous input and output
operations.
• Inherits all the functions from istream and ostream classes through
iostream. Rakesh Sharma
• File Opening : In order to perform operations, we have to create a file stream object and
connecting it with the file name. The classes ifstream, ofstream, and fstream can be used for
creating a file stream. The selection of the class is according to the operation that is to be
carried out with the file. The operation may be read or write. Two methods are used for the
opening of a file.
• Now the first step to open the particular file for read or write operation.
• Can open file by
1. passing file name in constructor at the time of object creation
2. using the open method

• Open File by using constructor


ifstream (const char* filename, ios_base::openmode mode = ios_base::in);

ifstream fin(filename, openmode) by default openmode = ios::in

ifstream fin(“filename”);
• Open File by using open method
Calling of default constructor
ifstream fin;
fin.open(filename, openmode)
fin.open(“filename”);
Rakesh Sharma
File Mode:

Rakesh Sharma
Using Constructor of the class:
When objects are created, a constructor is automatically executed, and objects are
initialized. In the same way, the file stream object is created using a suitable class,
and it is initialized with the file name. The constructor itself uses the file name as
the fist argument and opens the file. The class ofstream creates output stream
objects, and the class ifstream creates input stream objects.
• Consider the following examples:
a) ofstream out (“text”);
b) ifstream in(“list”);
❑In the statement (a), out is an object of the class ofstream; file name text is
opened, and data can be written to this file. The file name text is connected with
the object out. Similarly,
❑in the statement (b), in is an object of the class ifstream. The file list is opened
for input and connected with the object in. It is possible to use these file objects
in program statements such as stream objects.
❑Consider the following statements:
Rakesh Sharma
Consider the following statements:
cout<<“One Two Three”;
• The above statement displays the given string on the screen.

out<<“One Two Three”;


The above statement writes the specified string into the file pointed by the
object out as shown in Figure. The insertion operator << has been
overloaded appropriately in the ostream class to write data to the
appropriate stream.

Rakesh Sharma
• Similarly, in the following statements,

in>>string; // Reads data from the file into string where string
is a character array.
in>>num; // Reads data from the file into num where num is
an integer variable .

The in object reads data from the fiFor reading data from a file, we have to
create an object of the ifstream class.

Rakesh Sharma
Program to write the data in to the file.
#include <iostream.h> getch();
#include <fstream.h> }
void main()
{ In the above program, the statement
char name[15]; ofstream out (“text”) text is opened and
connected with the object out.
int age;
ofstream out("text"); Output:
cout<<"Enter Name:"<<endl; Enter Name: Amit
cin>>name; Enter Age: 20
cout<<"Enter Age:"<<endl; Contents of the file text:
cin>>age; Amit 20
out<<name<<"\t"; For checking the output open file from
out<<age <<endl; its location and check.
out.close(); // File is closed Rakesh Sharma
Program to Read the data from the file.
#include <iostream.h> cout<<"Age:"<<age;
#include <fstream.h> in.close();
void main() getch();
{ }
char name[15];
int age; Output:
ifstream in("text"); // Opens a Amit 20
file in read mode
in>>name;
in>>age;
cout<<"Name:"<<name<<endl;
Rakesh Sharma
Write a program to write and read data from file using object of
fstream class.
#include <iostream.h>
#include <fstream.h> f<<name<<"\t";
void main() f<<age <<endl;
{
char name[15]; f>>name;
int age; f>>age;
fstream f("text"); cout<<"\nName:"<<name<<endl;
cout<<"Age:"<<age;
cout<<"Enter Name:"<<endl; f.close();
cin>>name; getch();
cout<<"Enter Age:"<<endl; }
cin>>age;
Rakesh Sharma
Write a program to write and read text in a file.
Use ofstream and ifstream classes.
#include <iostream.h>
#include <fstream.h> ifstream in ("text");
void main() in>>name;
{ in>>age;
char name[15]; cout<<"\nName:"<<name<<endl;
int age; cout<<"Age:"<<age;
ofstream out("text"); in.close();
cout<<"Enter Name:"<<endl; getch();
cin>>name; }
cout<<"Enter Age:"<<endl; Output:
cin>>age; Enter Name : Amit
out<<name<<"\t"; Enter Age : 24
out<<age <<endl;
Rakesh Sharma Name : Amit
out.close(); // File is closed Age : 24
Using the open() function
• The open() function is used to open a file, and it uses the stream object.
• The open() function has two arguments. First is the file name, second is the mode and this is optional. The
mode specifies the purpose of opening a file; that is, read, write, append, and so on.
• If we don’t specify any mode default will be considered.
• In the following examples, the default mode is considered. The default values for ifstream is ios::in reading
only and for fstream is ios::out writing only.

• (A) Opening file for write operation


ofstream out; // Creates stream object out
out.open (“marks”); // Opens file and links with the object out
out.close() // Closes the file pointed by the object out
out.open (“result”); // Opens another file
Rakesh Sharma

• (B) Opening file for read operation


ifstream in; // Creates stream object in
in.open (“ marks”); // Opens file and link with the object in
in.close() ; // Closes the file pointed by object in
Write a program to open the file for writing and reading purposes.
Use open() function
#include <iostream.h> out<<age <<endl;
#include <fstream.h> out.close(); // File is closed
void main()
{ ifstream in;
char name[15]; in.open("Text");
int age; in>>name;
ofstream out; in>>age;
out.open("Text"); cout<<"\nName:"<<name<<endl;
cout<<"Enter Name:"<<endl; cout<<"Age:"<<age;
cin>>name; in.close();
cout<<"Enter Age:"<<endl; getch();
cin>>age; }
out<<name<<"\t";
Rakesh Sharma
Finding End of a File
• While reading data from a file, it is necessary to find where the file ends, that is,
the end of the file. The programmer cannot predict the end of the file. If in a
program, while reading the file, the program does not detect the end of the file,
the program drops in an infinite loop.
• To avoid this, it is necessary to provide correct instructions to the program that
detects the end of the file. Thus, when the end of the file is detected, the process
of reading data can be easily terminated.
• The eof() member function() is used for this purpose.

• The eof() stands for the end of the file. It is an instruction given to the program
by the operating system that the end of the file is reached.
• It checks the ios::eof bit in the ios::state. The eof() function returns the non-zero
value, when the end of the file is detected; otherwise, it is zero.

Rakesh Sharma
Write a program to read and display contents of file.
Use eof() function.
#include <iostream.h> }
#include<fstream.h> ofs.close();
void main()
{ ifstream ifs;
ofstream ofs; ifs.open("hello.txt");
char ch; cout<<"The Data from the file"<<endl;
ofs.open("hello.txt"); while(!ifs.eof())
cout<<"Enter some data at end type {
q(QUIT)"<<endl; ifs>>ch;
cin>>ch; cout<<ch;
while(ch!='q’) }
{ ifs.close();
ofs<<ch; getch();
cin>>ch; } Rakesh Sharma
Smart Pointers in C++
• Pointers are used for accessing the resources which are external to the
program like heap memory.
• If you are creating anything inside the heap memory then for accessing
the heap memory, we need to use pointers.
• The problem with the heap memory is that when you don’t need it then
you must deallocate the memory.
• And mostly the programmer shows laziness in writing the code for the
deallocation of objects from heap memory which causes severe
problems like memory leaks which will cause the program to crash.
• The languages like JAVA and C# provide a garbage collection
mechanism to deallocate the objects from heap memory that is not in
use.
• In C++ 11, smart pointers are introduced which will automatically
manage the heap memory and deallocate the object from the heap
memory when they are not in use or when the pointer is going out of
scope, automatically it will deallocate the memory.
Rakesh Sharma
I will show you the problem with the normal
pointer
#include <iostream> };
class Rectangle int Fun(int l, int b)
{ {
int Length; Rectangle *p(l, b);
int Breadth; int area = p->Area();
public: return area;
Rectangle(int l, int b) }
{ int main()
Length = l; {
Breadth = b; while (1)
} {
int Area() int Result = Fun(10, 20);
{ cout << Result << endl;
return Length * Breadth; }
} }
Rakesh Sharma
• Please observe the above. We have Rectangle class, Fun function, and main function.
Inside the Main function, we have an infinite while loop.
• And inside the while loop, we are calling function Fun infinite times. Function fun has a
pointer of type Rectangle class.
• It is dynamically created an object of class Rectangle in the heap memory. For a better
understanding, please have a look at the following diagram.
• Let’s assume that the Rectangle class has two variables called length and breadth of
integer types and assume that integer takes 2 Bytes, so for each object creation, it will
allocate 4 bytes of memory inside the heap.
• But the pointer variable p is going to be created inside the stack memory which will
point to the heap memory where the actual object is created.
• Now, once the Fun function execution completes, the p variable will be deleted from the
stack memory because it is a local variable to the function Fun but the new
Rectangle() that is allocated inside the heap memory will not be deallocated.
• Then control returns to the main function, and as we have written infinite while loop then
again Fun function will be called and another new Rectangle() object will be created
inside the heap memory.
• Pointer p will be deleted when the function ends but these Rectangle objects will not be
deleted from the memory. And every time we call the Fun function, it creates the objects
but does not delete them from the heap memory.

Rakesh Sharma
• This will cause leakage of memory from heap memory. Because while
the loop is infinite, at one stage because of a lack of heap memory
the program will crash.
• Then what is good practice? At the end of the function fun, we should
say delete p as shown in the below image.

int Fun(int l, int b)


{
Rectangle *p(l, b);
int area = p->Area();
return area;
Delete p;
}

Rakesh Sharma
#include <iostream> int area = p->Area();
delete p;
class Rectangle return area;
{ }
int Length; void main()
int Breadth; {
public: while (1)
Rectangle(int l, int b) {
{ int Result = Fun(10, 20);
Length = l; cout << Result << endl;
Breadth = b; }
} }
int Area() Because of the laziness or carelessness of the
programmer, this type of problem may arise in the
{ program.
return Length * Breadth; Some testing tools also check whether there is a
} problem of memory leak in the program. But still, it is
a good practice to deallocate the unused objects in
}; the program. We can also overcome this problem
using Smart Pointers in C++ which was introduced as
int Fun(int l, int b) part of C++ 11.
{
Rectangle *p = new Rectangle(l, b); Rakesh Sharma
Using Smart Pointers in:
• If we declare the smart pointer then they will automatically return Length * Breadth;
deallocate the object when the smart pointer is going out of the
scope. Let us show you how we can declare smart pointers in }
C++. };
• Unique Pointer . int Fun(int l, int b)
{
#include <iostream> unique_ptr<Rectangle> p(l, b));
#include<memory> int area = p->Area();
using namespace std; return area;
class Rectangle }
{ Void main()
int Length; {
int Breadth; while (1)
public: {
Rectangle(int l, int b) int Result = Fun(10, 20);
{ cout << Result << endl;
Length = l; }
Breadth = b; }
}
int Area()
{
Rakesh Sharma
• Here, inside the Fun function, we have pointer p of type unique_ptr of type
Rectangle class.
• And we have passed the new Rectangle (l, b) as the parameter which will
point p to the object of class Rectangle.
• By using this pointer, we have accessed the Area function of the
Rectangle object. In order to use the unique_ptr, we need to include the
#include<memory> header file.
• So, when the function ends and it is going out of the scope and then the
unique pointer p will be deleted and automatically it will also delete the
Rectangle object from the heap memory.
• So, unique_ptr will take care of the deletion of the object from the heap
memory.
• Internally, there is some other pointer that is pointing on the Rectangle
object but p is just a variable of type unique_ptr. So now we don’t have
to worry about memory leak problems.

Rakesh Sharma
Templates :

A template is a simple yet very powerful tool in C++. The simple idea is to pass
the data type as a parameter so that we don’t need to write the same code for
different data types. For example, a software company may need to sort() for
different data types. Rather than writing and maintaining multiple codes, we
can write one sort() and pass the datatype as a parameter.

C++ adds two new keywords to support templates: ‘template’ and ‘type name’. The second keyword can always be
replaced by the keyword ‘class’.

How Do Templates Work?

• Templates are expanded at compiler time. This is like macros. The difference is, that the compiler does type-checking
before template expansion. The idea is simple, source code contains only function/class, but compiled code may
contain multiple copies of the same function/class.

Rakesh Sharma

You might also like