Unit 4 Oops
Unit 4 Oops
Introduction to Memory management, new operator and delete operator Pointers to objects,
Pointers to Derived Classes-Virtual Functions
Introduction
ADDRESS OPERATOR &:All the variables defined in a program (including pointer variables) reside
at specific addresses
#include <iostream.h>
void main()
{
// define and initialize three integer variables
int a = 100;
int b = 200;
int c = 300;
// print the address and contents of the above variables
cout << “Address “ << & a << “ contains value “ << a << endl;
cout << “Address “ << & b << “ contains value “ << b << endl;
cout << “Address “ << & c << “ contains value “ << c << endl;
}
Run
Address 0xfff4 contains value 100
Address 0xfff2 contains value 200
Address 0xfff0 contains value 300
The pointer variable must be bound to a memory location. It can be achieved either by assigning the
address of a variable, or by assigning the address of the memory allocated dynamically.
The address of a variable can be assigned to a pointer variable as follows:
int_ptr = &marks;
where the variable marks is of type integer
Dereferencing of Pointers
Dereferencing is the process of accessing and manipulating data stored in the memory location pointed to
by a pointer. The operator *(asterisk) is used to dereference pointers in addition to creating them. A
pointer variable is dereferenced when the unary operator*(indirection operator)
#include <iostream>
using namespace std;
int main()
{
int *p;
int a=5;
p=&a;//address
cout<<"a:"<<a<<endl;
cout<<"p:"<<p<<"\t"<<"value "<<*p;//
return 0;
}
Output:
a:5
p:0x7ffff66eae9c value 5
Program
#include <iostream>
using namespace std;
int main()
{
int a[4]={10,20,30,40};
cout<<a<<endl;
cout<<&a[0];
cout<<endl<<endl;
cout<<*a<<endl;
cout<<a[0]<<endl;
return 0;
}
Output:
0x7ffe554894a0
0x7ffe554894a0
10
10
Note:
int *a;
a=new int;
Syntax2 :
datatype *p=new datatype;
int *a=new int
syntax3:
datatype *p=new datatype(value);
int *a=new int(6);
int *a = new( 100 );// creates a memory for an integer and initializes it with 100
float *rate = new( 5.5 );// creates a memory location for float and initializes it with 5.5.
int *a;
a = new int[ 100 ];
It creates a memory space for an array of 100 integers
float *b;
b = new float [ size ];
double *d;
d = new double[ size ]; // size is integer variable
char *city;
city = new char[ city_name_size ];// city_name_size is int variable
struct date
{
int day;
int month;
int year;
};
date *date_ptr;
date_ptr = new date;
delete operator:
Frees up memory space allocated by the new operator .Thus delete operator is used to return the
memory allocated by the new operator back to the memory pool. Memory thus released, will be reused by
other parts of the program.
delete a;
delete b;
delete d;
delete city;
delete date_ptr;
Demo2:
#include <iostream>
using namespace std;
int main()
{
int *p;
p=new int;
*p=10;
cout<<"The value of p "<<p;
cout<<"\nThe value at p "<<*p;
delete p;
return 0;
}
Output:
Demo3:
#include <iostream>
using namespace std;
int main()
{
int *p;
p=new int(8);
cout<<"The value of p "<<p;
cout<<"\nThe value at p "<<*p;
delete p;
return 0;
}
Output:
The value of p 0x558e4be4aeb0
The value at p 8
Demo4:
#include <iostream>
using namespace std;
int main()
{
int *p,i;
p=new int[5];
for(i=0;i<5;i++)
{
cin>>*(p+i);
}
for(i=0;i<5;i++)
{
cout<<*(p+i);
}
delete[] p; // Deallocate memor
return 0;
}
Output:
1
2
3
4
5
12345
#include <iostream>
using namespace std;
int main()
{
int *p,i;
p=new int[5];
for(i=0;i<5;i++)
{
cin>>p[i];
}
for(i=0;i<5;i++)
{
cout<<p[i];
}
delete[] p; // Deallocate memor
return 0;
}
Output:
1
2
3
4
5
12345
#include <iostream>
using namespace std;
int main()
{
int *p;
int n,i;
cout<<"Enter number of elements";
cin>>n;
p=new int[n];
for(int i=0;i<n;i++)
{
cin>>p[i];
}
for(int i=0;i<n;i++)
{
cout<<p[i]<<"\t";
}
cout<<"\n";
for(int i=0;i<n;i++)
{
cout<<*p<<"\t";
p++;
}
cout<<"\n";
for(int i=0;i<n;i++)
{
cout<<p<<"\t";
p++;
return 0;
}
Output:
Enter number of elements4
10
20
30
40
10 20 30 40
10 20 30 40
0x561afca016e0 0x561afca016e4 0x561afca016e8 0x561afca016ec
Note: name of an array refers to the base address or the address of the first element of the array. name of
an array often implicitly refers to the base address or the address of the first element of the array.
Pointers to objects
A class can be instantiated at runtime and objects created by such instantiation are called
dynamic objects. , it creates a live object. The new operator is used to create dynamic objects and the
delete operator is used to release the memory allocated to the dynamic object by the new operator. A
pointer to a variable can be defined to hold the address of an object, which is created statically or
dynamically.
Pointers can be used to hold addresses of objects, just as they can hold addresses of primitive and
user defined data items. The need for using pointers to objects becomes clear when objects are to be
created while the program is being executed, which is an instance of dynamic allocation of memory.
The address operator & can be used to get the address of an object, which is defined statically
during compile time.
ptr_to_object = &object;
The & operator in the expression &object returns the address of the object and the same is
initialized to a pointer variable ptr_to_object.
The operator -> can also be used to access members of an object using a pointer to objects.
The expression to access a class member using a pointer is as follows:
pointer_to_object -> member_name
or
*pointer_to_object. member_name
The member to be accessed through the object pointer can be either a data or function member
Demo1:
#include<iostream>
using namespace std;
class Student
{
int reg;
float marks;
public:
void get()
{
cout<<"Enter reg and marks";
cin>>reg>>marks;
}
void put()
{
cout<<"The reg is"<<reg<<endl;
cout<<"The marks is"<<marks<<endl;
}
};
int main()
{
Student *s1;
s1=new Student;
s1->get();
s1->put();
return 0;
}
Demo3:
#include<iostream>
using namespace std;
class Student
{
int reg;
float marks;
public:
void get()
{
cout<<"Enter reg and marks";
cin>>reg>>marks;
}
void put()
{
cout<<"The reg is"<<reg<<endl;
cout<<"The marks is"<<marks<<endl;
}
};
int main()
{
Student *p1;
Student s1;
p1=&s1;
p1->get();
p1->put();
Student *s2;
s2=new Student;
s2->get();
s2->put();
return 0;
}
Output:
Enter reg and marks 4 50
The reg is4
The marks is50
Enter reg and marks 6 80
The reg is6
The marks is80
Demo1:
#include <iostream>
using namespace std;
class A
{
public:
void display()
{
cout<<"Inside A"<<endl;
}
};
class B:public A
{
public:
void display()
{
A::display();
cout<<"Inside B";
}
};
int main()
{
A *a=new A;
a->display();
B *b=new B;
b->display();
return 0;
}
Output:
Inside A
Inside A
Inside B
#include<iostream>
using namespace std;
class Student
{
int reg;
float marks;
public:
void get()
{
cout<<"Enter reg and marks";
cin>>reg>>marks;
}
void put()
{
cout<<"The reg is"<<reg<<endl;
cout<<"The marks is"<<marks<<endl;
}
};
class c
{
public:
void display()
{
cout<<"hai";
}
};
int main()
{
Student *p1;
Student s1;
p1=&s1;
p1->get();
p1->put();
Student *s2;
s2=new Student;
s2->get();
s2->put();
cout<<sizeof(s1)<<endl;
cout<<sizeof(s2)<<endl;
cout<<sizeof(int)<<endl;
c d;
cout<<sizeof(d);
return 0;
}
Ouput:
Enter reg and marks5 6
The reg is5
The marks is6
Enter reg and marks7 9
The reg is7
The marks is9
8
8
4
1
Demo
#include <iostream.h>
class someclass
{
public:
int data1;
char data2;
someclass()
{
cout << “Constructor someclass() is invoked\n”;
datal = 1, data2 = ‘A’;
}
~someclass()
{
cout << “Destructor ~someclass() is invoked\n”;
}
void show()
{
cout << “data1 = “ << data1;
cout << “ data2 = “ << data2 << end1;
}
};
void main(void)
{
someclass *ptr; // define a pointer to object of class someclass
someclass objectl; // object of type someclass created statically
ptr = &object1;
cout << “Accessing object through object1.show() ...” << end1;
object1.show();
cout << “Accessing object through ptr->show()...” << end1;
ptr->show(); //it can be *ptr.show();
}
Run
Constructor someclass() is invoked
Accessing object through object1.show() ...
datal = 1 data2 = A
Accessing object through ptr->show()...
datal = 1 data2 = A
Destructor ~someclass() is invoked
The statement
ptr->show();
or
*ptr.show()
invokes the member function show() of the object pointed to by the pointer ptr.
The use of a pointer to the objects of a base class with the objects of its derived class raises a
new problem. It does not allow access even to public members of a derived class.
That is, it allows access only to those members inherited from the base class but not to the
members which are defined in the derived class.
Even in case, any member of the D class has the same name as one of the members of the B
class, reference to it using the base class pointer b will always access the base-class member and not the
derived-class member.
To access member function of derived class those are not defined in base class,
((derived_classname*) poinertobject))->derviedclass_memberfunction(unique to derived class)
Example
#include <iostream>
using namespace std;
class B{
protected :
int a;
public:
B(int a1)
{
a=a1;
}
int getvalue()
{
return a;
}
};
class D:public B
{
protected:
int b;
public:
D(int a1,int b1):B(a1)
{
b=b1;
}
int getvalue()
{
return b;
}
void somefunction()
{
cout<<"function in derived";
}
};
int main()
{
B *b;
b=new B(70);
cout<<b->getvalue()<<endl;
b=new D(10,20);
cout<<"base class value:"<<b->getvalue()<<endl;
cout<<"derived class value:"<<((D*)b)->getvalue();
return 0;
}
Note:
A base class pointer may address an object of its own class or an object of any class derived from the
base class is a one-way route. Address an object of the base class. If a pointer to a derived class is
allowed to address the base-class object, the compiler will expect members of the derived class to be in
the base class also.
Virtual Functions
A virtual function is a member function in the base class that we expect to redefine in derived
classes. In C++, it indicates the form of a member function that can be changed at runtime. Such
member functions are called virtual functions
When function name and prototype is same in both base and derived class, the appropriate
member function could be selected while program is running. This is known as run time
polymorphism.
When we use same function name in both base and derived class, the function in the base is
declared as virtual using the keyword virtual preceding its normal declaration.
C++ determines which function to use at runtime based on the type of object pointed by base
pointer.
A single pointer variable is used to refer to the object of different class.
C++ supports a mechanism known as virtual function to achieve run time polymorphism.
In C++, a function call can be bound to the actual function either at compile time or at runtime.
Resolving a function call at compile time is known as compile-time or early or static binding whereas,
resolving a function call at runtime is known as runtime or late or dynamic binding.
Runtime polymorphism allows to postpone the decision of selecting the suitable member functions until
runtime. In C++, this is achieved by using virtual functions
Characteristic of virtual function
Virtual functions must be members of some class.
They cannot be static members.
It can be a friend of another class.
We cannot have a virtual constructors but have virtual destructors.
They can be accesses using object pointers.
A virtual functions in a base class must be defined even though it may not be used.
If a virtual function is defined in the base class, it need not be necessarily redefined in derived
class. In such case calls invoke base function
Example1:
Example demo
#include <iostream>
using namespace std;
class Base
{
public:
virtual void display()
{
cout<<"Display base"<<endl;
}
};
class Derived : public Base
{
public:
void display()
{
cout<<"Display derived";
}
};
int main()
{
Base b,*bptr;
Derived d;
b.display();
d.display();
cout<<"\n---------------------------------";
cout<<"\nPoniters points to base\n";
bptr=&b;
bptr->display();
Display base
Display derived
---------------------------------
Poniters points to base
Display base
Poniters points to derived
Display derived
Without-virtual keyword
#include <iostream>
using namespace std;
class Base
{
public:
void display()
{
cout<<"Display base"<<endl;
}
};
class Derived:public Base
{
public:
void display()
{
cout<<"Display derived";
}
};
int main()
{
Base b,*bptr;
Derived d;
return 0;
}
Output:
Poniters points to base
Display base
#include <iostream>
using namespace std;
class A
{
public:
void display()
{
cout<<"Inside A"<<endl;
}
};
class B:public A
{
public:
void display()
{
A::display();
cout<<"Inside B";
}
};
int main()
{
A *p;
A a;
p=&a;
p->display();
B b;
p=&b;
p->display();
return 0;
}
Output:
Inside A
Inside A
public:
virtual void display()
{
cout<<"Inside A"<<endl;
}
};
class B:public A
{
public:
void display()
{
//A::display();
cout<<"Inside B";
}
};
int main()
{
A *p;
A a;
p=&a;
p->display();
B b;
p=&b;
p->display();
return 0;
}
Output:
Inside A
Inside B
Demo3
#include <iostream>
using namespace std;
class A
{
public:
virtual void display()
{
cout<<"Inside A"<<endl;
}
};
class B:public A
{
public:
void display()
{
cout<<"Inside B";
}
};
int main()
{
A *p;
A *a=new A;
p=a;
p->display();
B *b=new B;
p=b;
p->display();
return 0;
}
Inside A
Inside B
Demo4
#include <fstream>
#include <iostream>
using namespace std;
void calculate()
{
cout << "Enter one side your of Square: ";
cin >> side;
int main()
{
Demo5
#include <fstream>
#include <iostream>
using namespace std;
};
// Declaration of Derived class
class Rectangle : public Shape {
public:
int width, height, area;
void calculate()
{
cout << "Enter Width of Rectangle: ";
cin >> width;
void calculate()
{
cout << "Enter one side your of Square: ";
cin >> side;
Output:
Enter Width of Rectangle: 7
Enter Height of Rectangle: 5
Area of Rectangle: 35
Enter one side your of Square: 8
Area of Square: 64
#include <iostream>
using namespace std;
class A
{
public:
virtual void show() = 0; // Pure Virtual Function
};
class B:public A
{
public:
void show()
{
cout<< "Derived class";
}
};
int main()
{
B b;
b.show();
return 0;
}
Output:
Derived class
Abstract class
Demo6
#include <iostream>
using namespace std;
class A
{
public:
virtual void display()=0;//pure virtual function(or)abstract class
};
class B:public A
{
public:
void display()
{
//A::display();
cout<<"Inside B"<<endl;
}
};
int main()
{
B b;
b.display();
A *a;
a=&b;
a->display();
return 0;
}
Inside B
Inside B
#include <fstream>
#include <iostream>
using namespace std;
};
// Declaration of Derived class
class Rectangle : public Shape {
public:
int width, height, area;
void calculate()
{
cout << "Enter Width of Rectangle: ";
cin >> width;
void calculate()
{
cout << "Enter one side your of Square: ";
cin >> side;
Output:
Enter Width of Rectangle: 6
Enter Height of Rectangle: 5
Area of Rectangle: 30
Enter one side your of Square: 4
Area of Square: 16
UNIT-IV-part2
Basics of Exception Handling, Types of exceptions, Exception Handling Mechanism, Throwing and
Catching Mechanism, rethrowing an Exception, Specifying Exceptions
Throw
• The keyword throw is used to raise an exception when an error is generated in the computation.
• The throw expression initializes a temporary object of the type T (to match the type of argument
arg) used in throw (T arg)
Example1:
#include<iostream>
using namespace std;
int main() {
int a, b, c;
float d;
try {
if ((a - b) != 0) {
d = c / (a - b);
cout << "Result is:" << d;
} else {
throw (a - b);
}
} catch (int i) {
cout << "Answer is infinite because a-b is:" << i;
}
return 0;
}
Output:
Enter the value of a:10
Enter the value of b:10
Enter the value of c:5
Answer is infinite because a-b is:0
Example2:
int a[5]={10,20,30,40,50};
int i;
cin>>i;
try
{ if(i<0 || i>5)
throw 10;
else
cout<<a[i];
}
catch(int a)
{
cout<<"out of bound exception";
}
cout<<"end";
return 0;
}
7
out of bound exceptionend
Example3
#include <iostream>
using namespace std;
class positive{};
class negative{};
class zero{};
int main()
{
int num;
cout<<"Enter the number";
cin>>num;
try
{
if(num==0)
throw zero();
else if(num<0)
throw negative();
else
throw positive();
}
catch(positive)
{
cout<<"positive exception";
}
catch(negative)
{
cout<<"negative exception";
}
return 0;
}
Output:
Enter the number 5
Positive exception
Example 4
#include <iostream>
using namespace std;
class positive{};
class negative{};
class zero{};
int main()
{
int num;
cout<<"Enter the number";
cin>>num;
try
{
if(num==0)
throw zero();
else if(num<0)
throw negative();
else
throw positive();
}
catch(positive)
{
cout<<"positive exception";
}
catch(negative)
{
cout<<"negative exception";
}
return 0;
}
Enter the number0
terminate called after throwing an instance of 'zero'
Example:
If a function throws an exception not listed in its specification, the program will call the function
unexpected().unexpected() function inturn call terminate() function
Program1:
#include <iostream>
using namespace std;
class positive {};
class negative {};
class zero {};
// this function can raise only positive and negative exceptions
void what_sign( int num ) throw( positive, negative,Zero )
{
if( num > 0 )
throw positive();
else
if(num < 0)
throw negative();
else
throw zero(); // unspecified exception
}
int main()
{
int num;
cout << "Enter any number: ";
cin >> num;
try
{
what_sign( num );
}
catch( positive )
{ cout << "+ve Exception"; }
catch( negative )
{ cout << "-ve Exception"; }
catch( zero )
{ cout << "0 Exception"; }
return 0;
}
Enter any number: 5
+ve Exception
Program2:
#include <iostream>
using namespace std;
class positive {};
class negative {};
class zero {};
// this function can raise only positive and negative exceptions
void what_sign( int num ) throw( positive, negative )
{
if( num > 0 )
throw positive();
else
if(num < 0)
throw negative();
else
throw zero(); // unspecified exception
}
int main()
{
int num;
cout << "Enter any number: ";
cin >> num;
try
{
what_sign( num );
}
catch( positive )
{ cout << "+ve Exception"; }
catch( negative )
{ cout << "-ve Exception"; }
catch( zero )
{ cout << "0 Exception"; }
return 0;
}
Output1:
Enter any number: 5
+ve Exception
Output2:
Ouput:
Enter any number: 6
terminate called after throwing an instance of 'positive'
Example1
#include <iostream>
using namespace std;
class positive{};
class negative{};
class zero{};
int main()
{
int num;
cout<<"Enter the number";
cin>>num;
try
{
if(num==0)
throw zero();
else if(num<0)
throw negative();
else
throw positive();
}
catch(...)
{
cout<<"Exception";
}
return 0;
}
Output:
Enter the number 8
Exception
Rethrowing an exception
• If a function does not want to take any corrective action in response to an exception, it can pass
the same to the caller of a function.
• The throw construct without an explicit exception parameter raises the previous exception. An
exception must currently exist, otherwise terminate() is invoked.
• Syntax:
throw;
Exampe1
#include <iostream>
#include<conio.h>
using namespace std;
void exceptionFunction() {
try {
throw 0;
} catch (int i) {
cout << "\nException1:" << i;
throw;
}
}
int main() {
int var = 0;
cout << "Simple C++ Program for Rethrowing Exception Handling : In Function\n";
try {
exceptionFunction();
}
catch (int ex) {