OBJECT ORIENTED PROGRAMMING IN C++ �[UNIT-III]
U4.1
Learning Objectives
U4.2
Inheritance�
U4.3
Inheritance Examples
U4.4
Derived class declaration
Class DerivedClass:[ VisibilityMode] BaseClass
{
//member of derived class
//can access member of base class
}
U4.5
visibility mode
U4.6
Forms of Inheritance
U4.7
Types of
Inheritance
U4.8
Deriving a Class
U4.9
Base class visibility | Derived class visibility | ||
| Public | Private | Protected |
Private | Not inherited | Not inherited | Not inherited |
Protected | Protected | Private | Protected |
Public | Public | Private | Protected |
Visibility of Inherited Members
U4.10
class A // base class { .......... };
class B : acess_specifier A // derived class { ........... } ;
U4.11
#include <iostream>
using namespace std;
class base //single base class
{ public: int x;
void getdata()
{ cout << "Enter the value of x = "; cin >> x; } };
class derive : public base //single derived class
{ private: int y; public:
void readdata()
{ cout << "Enter the value of y = "; cin >> y; }
void product() { cout << "Product = " << x * y; } };
int main()
{ derive a; //object of derived class
a.getdata();
a.readdata();
a.product(); return 0; } //end of program
U4.12
Program of Single Inheritance�
#include<iostream.h> #include<conio.h>
class person //Base class or Super class
{ char name[20]; int age; public: void read_data(); void display_data();};
class student : public person // Derived class or Sub class
{ int roll; int marks; char grade;
public : void get_data(); char compute_grade(); void show_data(); };
void person :: read_data()
{ cout<<”\n Enter name:”; cin>>name; cout<<”\n Enter age: “; cin>>age;}
void person :: display_data()
{cout<<”\n Name: “<< name; cout<< “\n Age: “ << age; }
U4.13
Program of Single Inheritance�
void student :: get_data()
{read_data(); cout<< “\n Enter Roll :”; cin>>roll;
cout<< “\n Enter Marks: “; cin>> marks; grade = compute_grade();}
char student :: compute_grade()
{char gd; if (marks<80) gd = ’B’ else gd = ‘A’; return (gd);}
void student :: show_data()
{cout << “\n Roll: “ << roll;cout << “\n Marks: “ << marks;
cout<< “\n Grade: “ <<grade;}
main(){student s1; // Create an object of student type
s1.getdata();// Read data of a student
cout<<”\n The student data is…:; cout<<”\n”;
obj.dispaly_data(); obj.show_data(); return(0); }
U4.14
Multilevel Inheritance�
#include<iostream.h> #include<conio.h>
class A1{protected: char name[15]; int age; };
class A2:public A1 // First level derivation
{ protected: float height; float weight; };
class A3:public A2 // Second level derivation
protected: char sex; public: void get() // Reads data
{ cout<<”Name: “; cin>> name; cout<<”Age: “; cin>> age;
cout<<”Sex: “; cin>> sex; cout<<”Height: “; cin>> height;
cout<<”Weight: “; cin>> weight; } void show() // Displays data
cout<<”\n Name: “ << name; cout<<”\n Age: “ << age<< “Years”;
cout<<”\n Sex: “ << sex; cout<<”Height: “ << height << ”Feets”;
cout<<”Weight: “ << weight << “kg”;}};
U4.15
Multilevel Inheritance
void main()
{
A3 X; // Object declaration
X.get(); // Reads data
X.show(); // Displays data
}
U4.16
Multiple Inheritance
#include<iostream.h>
class A {protected: int a;};// class A declaration
class B {protected: int b;};// class B declaration
class C {protected: int c;};// class C declaration
class D {protected: int d;};// class D declaration
class E: public A, B, C, D // Multiple Derivation
{int e;
public:
void getdata()
{cout<<”\n Enter values of a, b, c, d & e: ”;
cin>>a>>b>>c>>d>>e;}
U4.17
Multiple Inheritance
void showdata()
{cout<<”\n a= “ <<a <<”b= “ <<b<< “c = “ << c << “d = ” <<d << “e= “ <<e;}};
void main()
{E x; // Object declaration
x.getdata(); // Reads data
x.showdata(); //Displays data
}
OUTPUT:
Enter values of a, b, c, d & e: 1 2 4 8 16
a=1 b=2 c=4 d=8 z=16
U4.18
Example of Hierarchial Inheritance�
Instead of starting from the scratch, we can simply derive a new class employee from the base class person.
#include<iostream.h> #include<conio.h>
class person //Base class or Super class
{char name[20]; int age;
public: void read_data();void display_data();};
class student : public person // Derived class or Sub class
{int roll; int marks; char grade; public : void get_data();
char compute_grade(); void show_data();};
class employee : public person
{float bp; float hr; float sal;
public:void input_emp(); float compute_salary(); void disp_emp();};
U4.19
Example of Hierarchical Inheritance�
void employee :: input_emp()
{read_data(); // Read name & age from the base class
cout<< “\n Enter Basic Pay:”; cin >> bp;
cout<<”\n Enter HRA :”; cin>>hr;
sal = compute_salary();}
float employee :: compute_salary()
{float total; total=bp+hr+2.5*bp; return(total);}
void employee :: disp_emp()
{cout<< “\n B.P. : “ << bp; cout<< “\n H.R. : “ << hr;
cout<< “\n Salary : “ << sal; }
U4.20
Example of Hierarchial Inheritance�
void person :: read_data()
{cout<<”\n Enter name:”; cin>>name;
cout<<”\n Enter age: “; cin>>age;}
void person :: display_data()
{cout<<”\n Name: “<< name;
cout<< “\n Age: “ << age;}
void student :: get_data()
{read_data(); //read name & age from base class
cout<< “\n Enter Roll :”; cin>>roll;
cout<< “\n Enter Marks: “; cin>> marks;
grade = compute_grade();}
U4.21
Example of Hierarchial Inheritance�
char student :: compute_grade()
{char gd;
if (marks<80)
gd = ’B’
else gd = ‘A’;
return (gd);}
void student :: show_data()
{
cout << “\n Roll: “ << roll;
cout << “\n Marks: “ << marks;
cout<< “\n Grade: “ <<grade;
}
U4.22
Example of Hierarchial Inheritance�
main()
{student s1; // Create an object of student type
employee e1; // Create an object of employee tppe
s1.getdata();// Read data of a student
cout<<”\n The student data is…:;
obj.dispaly_data();//inherit function from class person
obj.show_data();
e1.input_emp(); // Read Employee data
cout<<”\n The Employee data is…:;
e1.dispay_data ();// Inherit function from class person to display
e1. disp_emp (); // Display Employee details
return(0);}
U4.23
U4.24
Constructors/Destructors order of Inheritance
U4.25
Abstract Classes
class Account { public: Account( double d ); // Constructor.
virtual double GetBalance(); // Obtain balance.
virtual void PrintBalance() = 0; // Pure virtual function.
private: double _balance; };
U4.26
Abstract Classes
class Animal {�public: virtual void speak() = 0;};
class Bird : public Animal {�public: virtual void speak() { printf("twitter"); }};
class Mammal : public Animal {�public: virtual void speak() { printf("can't speak"); }� void bark() { printf("can't bark"); }};
class Cat : public Mammal {�public: void speak() { printf("meow"); }� virtual void purr() { printf("purrrrr"); }};
class Dog : public Mammal {�public: virtual void speak() { printf("wouf"); }� void bark() { printf("wouf"); }
};
U4.27
Overriding in C++
U4.28
Restrictions on using Abstract Classes
U4.29
Example
class base { public: base() {}
virtual ~base()=0; };
// Provide a definition for destructor.
base::~base() {}
class derived: public base { public: derived() {}
~derived(){} };
int main() {
derived *pDerived = new derived;
delete pDerived; }
U4.30
Inner Working of Virtual Functions
U4.31
The virtual table
U4.32
U4.33
class Base
{
public:
virtual void function1() {};
virtual void function2() {};
};
class D1: public Base
{
public:
virtual void function1() {};
};
class D2: public Base
{
public:
virtual void function2() {};
};
Because there are 3 classes here, the compiler will set up 3 virtual tables: one for Base, one for D1, and one for D2.
The compiler also adds a hidden pointer to the most base class that uses virtual functions. Although the compiler does this automatically,
U4.34
we’ll put it in the next example just to show where it’s added:
class Base
{
public:
FunctionPointer *__vptr;
virtual void function1() {};
virtual void function2() {};
};
class D1: public Base
{
public:
virtual void function1() {};
};
class D2: public Base
{
public:
virtual void function2() {};
};
U4.35
U4.36
U4.37
Here’s a picture
of this
graphically:
U4.38
Virtual Base Classes
U4.39
Virtual Base Classes
U4.40
Virtual Base Classes
U4.41
Example -objects of type derived can directly access the public members of base:
#include <iostream>
using namespace std;
class base {
int i, j;
public:
void set(int a, int b)
{ i=a; j=b;
}
void show() {
cout << i << " " << j << "\n"; }
};
class derived : public base
{int k;
public:
derived(int x)
{ k=x; }
void showk() { cout << k << "\n"; }};
int main()
{derived ob(3);
ob.set(1, 2); // access member of base
ob.show(); // access member of base
ob.showk(); // member of derived class
return 0;
}
U4.42
When the base class is inherited by using the private access specifier, all public and protected members of the base class become private members of the derived class. For example, the following program will not even compile because both set( ) and show( ) are now private elements of derived:
// This program won't compile.
#include <iostream>
using namespace std;
class base {
int i, j;
public:
void set(int a, int b) { i=a; j=b; }
void show() { cout << i << " " << j << "\n";}
};
U4.43
// Public elements of base are private in derived.
class derived : private base
{
int k;
public:
derived(int x) { k=x; }
void showk() { cout << k << "\n"; }
};
int main()
{
derived ob(3);
ob.set(1, 2); // error, can't access set()
ob.show(); // error, can't access show()
return 0;
}
U4.44
Protected members behave differently. If the base class is inherited as public, then the base class' protected members become protected members of the derived class and are, therefore, accessible by the derived class. By using protected, you can create class members that are private to their class but that can still be inherited and accessed by a derived class.
#include <iostream>
using namespace std;
class base {
protected:
int i, j; // private to base, but accessible by derived
public:
void set(int a, int b) { i=a; j=b; }
void show() { cout << i << " " << j << "\n"; }
};
U4.45
class derived : public base {
int k;
public:
// derived may access base's i and j
void setk() { k=i*j; }
void showk() { cout << k << "\n"; }
};
int main()
{
derived ob;
ob.set(2, 3); // OK, known to derived
ob.show(); // OK, known to derived
ob.setk();
ob.showk();
return 0;
}
U4.46
In this example, because base is inherited by derived as public and because i and j are declared as protected, derived's function setk( ) may access them. If i and j had been declared as private by base, then derived would not have access to them, and the program would not compile.
U4.47
It is possible to inherit a base class as protected. When this is done, all public and protected members of the base class become protected members of the derived class.
For example,
#include <iostream>
using namespace std;
class base {
protected:
int i, j; // private to base, but accessible by derived
public:
void setij(int a, int b) { i=a; j=b; }
void showij() { cout << i << " " << j << "\n"; }
};
U4.48
// Inherit base as protected.
class derived : protected base
{
int k;
public:
// derived may access base's i and j and setij().
void setk()
{
setij(10, 12);
k = i*j;
}
// may access showij() here
void showall()
{
cout << k << " ";
showij();
}
};
U4.49
int main()
{
derived ob;
// ob.setij(2, 3); // illegal, setij() is protected member of derived
ob.setk(); // OK, public member of derived
ob.showall(); // OK, public member of derived
// ob.showij(); // illegal, showij() is protected member of derived
return 0;
}
As you can see by reading the comments, even though setij( ) and showij( ) are public members of base, they become protected members of derived when it is inherited using the protected access specifier. This means that they will not be accessible inside main( ).
U4.50
It is possible for a derived class to inherit two or more base classes. For example, in this short example, derived inherits both base1 and base2.
An example of multiple base classes.
#include <iostream>
using namespace std;
class base1 {
protected:
int x;
public:
void showx() { cout << x << "\n"; }
};
class base2 {
protected:
int y;
public:
U4.51
void showy() {cout << y << "\n";}
};
// Inherit multiple base classes.
class derived: public base1, public base2 {
public:
void set(int i, int j) { x=i; y=j; }
};
int main()
{
derived ob;
ob.set(10, 20); // provided by derived
ob.showx(); // from base1
ob.showy(); // from base2
return 0;
}
U4.52
how an access declaration works,Ex-
class base {
public:
int j; // public in base
};
// Inherit base as private.
class derived: private base {
public:
// here is access declaration
base::j; // make j public again
.
.
.
};
Because base is inherited as private by derived, the public member j is made a private
member of derived. However, by including
base::j;
U4.53
Aggregation or containership or object Composition in C++
A special form of association that models a whole-part relationship between an aggregate (the whole) and its parts.
Aggregation is also called whole-part or HasA.
For example, an Aircraft contains an Engine or in other words, an Aircraft has an Engine.
U4.54
Aggregation
• Represents a “has-a” (whole-part) relationship
• An object of the whole has objects of the part
U4.55
For example, among other things, a car consists of tires and an engine. Note that the opposite of aggregation is decomposition.
U4.56
Aggregation
U4.57
A form of aggregation with strong ownership and coincident lifetime as part of the whole. Parts with non-fixed multiplicity may be created after the composite itself, but once created they live and die with it (i.e., they share lifetimes). Such parts can also be explicitly removed before the death of the composite.
U4.58
It is represented as darked diamond at the whole part.
example:
class A{
//some code
};
class B
{
A aa; // an object of class A;
// some code for class B;
};
In the above example we see that an object of class A is instantiated with in the class B. so the object class A dies when the object class B dies.we can represnt it in diagram like this.
class A
class B
U4.59
Object Composition
U4.60
Containership �
class address {
int hno;
char colony[20];
char dist[20];
char state[20];
int pincode;
public:
void get_data();
void show_data();
};
class person {
char name[20];
address resadd;
};
U4.61
Containership �
U4.62
class Department�{�protected:
int id;�char name[50];
public:
void setDepartment()�{�cout<>id;�cout<>name;�}�void displayDepartment()�{�cout<<"\n Department ID is:"<<id<<"\n";�cout<<"\n Department Name is:"<<name<<"\n";�}};
class Employee�{�protected:
int eid;�char ename[50];�Department dobj;
public:
void setEmployee()�{�cout<>eid;�cout<>ename;�dobj.setDepartment();�}�void displayEmployee()�{�cout<<"\n Employee ID is:"<<eid<<"\n";�cout<<"\n Employee Name is:"<<ename<<"\n";�dobj.displayDepartment();�}�};
U4.63
Destructors in Derived Classes
#include <iostream.h>
class B1{
public :
B1(){cout<< “no argument constructor in B1”;}
~B1(){cout<< “destructor in B1”;}
};
class B2{
public :
B2(){cout<< “no argument constructor in B2”;}
~B2(){cout<< “destructor in B2”;}
};
U4.64
class D: public B1, public B2
{
public :
D(){cout<< “no argument constructor in D”;}
~D(){cout<< “destructor in D”;}
};
void main(){ D objd;}
Run
no argument constructor in B1
no argument constructor in B2
no argument constructor in D
destructor in D
destructor in B2
destructor in B1
U4.65
Over loaded Member Functions
Classname :: Membername ( ) ;
U4.66
class a{
public :
void fn(){ cout<<"base\n";}};
class b: public a{
public :
void fn(){ cout<<"derived\n";}};
void main(){
b obj;
obj.fn();
obj.a::fn(); }
U4.67
Abstract Classes
U4.68
Conclusion
U4.69
POLYMORPHISM / OVERLOADING
Example: Draw a shape (Box, Triangle, Circle etc.), Move ( Chess, Traffic, Army).
Example: ‘+’ is used for adding numbers / to concatenate two string / Sets of Union and so on.
U4.70
POLYMORPHISM (Contd.)
U4.71
Function Overloading
U4.72
What is the need for function overloading? �
U4.73
How to implement function overloading?�
U4.74
Contd…
U4.75
Contd…
U4.76
Unary Operator Overloading
// Program1.cpp: Index class with operator overloading for increment operator
#include < iostream.h>
class Index
{ private: int value; // Index Value
public:
Index ( ) // No argument constructor
{ value = 0; }
int GetIndex( ) // Index Access
{ return value; }
void operator + +( ) // prefix or postfix increment operator
{
value = value + 1; // value+ + ; }} ;
U4.77
Unary Operator Overloading
void main( )
{ Index idx1, idx2; // idex1 and idx2 are objects of Index class
// display index values
cout << “ \nIndex1 = “ << idx1 . GetIndex ( ) ;
cout << “ \nIndex2 = “ << idx2 . GetIndex ( ) ;
// Advance Index objects with + + operators
+ + idx1; // equivalent to idx1. operator + + ( ) ;
idx2 + + ;
idx2 + + ;
cout << “ \ nIndex1 = “ << idx1. GetIndex ( ) ;
cout << “ \ nIndex2 = “ << idx2. GetIndex ( ) ;
}
U4.78
Operator Returns Values�
The operator function in the previous program Program1.cpp has a subtle defect. An attempt to use an expression such as;
idx1= idx2++;
will lead to a compilation error like Improper Assignment because the return type of operator++ is defined as void type. Such an assignment operation can be permitted after modifying the return type of the operator ++() member function of the index class.
//Program2.cpp: Index class with overloaded operator returning an object
#include < iostream.h>
class Index{ private: int value; // Index Value
public: Index ( ) // No argument constructor
{ value = 0; }
int GetIndex( ) // Index Access
{ return value; }
U4.79
Operator Returns Values�
Index operator + +( ) // Returns nameless object of class Index
{ Index temp; // temp object
value = value + 1; // update index value
temp.value = value; // Initialise temp object
return temp; // Returns temp object
}} ;
void main( )
{Index idx1, idx2; // idex1 and idx2 are objects of Index class
cout << “ \nIndex1 = “ << idx1 . GetIndex ( ) ;
cout << “ \nIndex2 = “ << idx2 . GetIndex ( ) ;
// Returned object of idx2+ + is assigned to object idx1
idx1 = idx2++; // invokes the overloaded function
idx2 + + ; // Returned object of idx2++ is unused
cout << “ \ nIndex1 = “ << idx1. GetIndex ( ) ;
cout << “ \ nIndex2 = “ << idx2. GetIndex ( ) ;}
U4.80
Binary Operator Overloading
Complex numbers consists of two parts: real part and imaginary part. It is represented as ( x+iy), where x is the real part and y is the imaginary part. The process of performing the addition operation is illustrated below. Let c1, c2and c3 be three complex numbers represented as follows:c1 = x1 + i y1; c2 = x2 + i y2;
The operation c3 = c1 + c2 is given by
c3 = ( c1 .x1 + c2 .x2 ) + i ( c1. y1 + c2. y2 ) ;
// Complex1.cpp: Complex numbers operations with binary operator overloading
# include < iostream.h> class complex{ private : float real ; float imag ;
complex number
public : complex ( ) // no argument constructor
{ real = imag = 0 . 0 ;}
U4.81
Binary Operator Overloading
void getdata ( ) // read complex number
{ cout << “Real Part ? “ ; cin >> real ;
cout << “Imag Part ? “ ; cin >> imag ; }
complex operator + ( complex c2 ) ; // complex addition
void outdata ( char *msg ) // display complex number
{ cout << endl << msg ; cout << “ ( “ << real ;
cout << “ , “ << imag<<“ ) “ ; }} ;
// add default and c2 complex objects
complex complex : : operator + ( complex c2 )
{ complex temp ; // object temp of complex class
temp . real = real + c2 . real ; //add real parts
temp . imag = imag = c2 . imag ; //add imaginary parts
return ( temp ) ; // return complex object
}
U4.82
Binary Operator Overloading
void main ( )
{
complex c1, c2 , c3 ; // c1 , c2 , c3 are object of complex class
cout << “ Enter Complex Number c1 . . “ << endl ;
cl . getdata ( ) ;
cout << “ Enter Complex Number c2 . . “ << endl ;
c2 . getdata ( ) ;
c3 = c1 + c2 ; // add c1 and c2 and assign the result to c3 i.e; c3 = c1 . operator+ ( c2 ) ;
c3 . outdata ( “ c3 = c1 + c2 : “ ) ; // display result
}
U4.83
C++ virtual function is,
Pointer object of base class can point to any object of derived class but reverse is not true.
Virtual function
U4.84
Need For Virtual Functions�
When objects of different class in a class hierarchy, react to the same message in their own unique ways, they are said to exhibit polymorphic behavior. This program has the base class Father and the derived class Son and has a member function show() with the same name and prototype. In C++, a pointer to the base class can be used to point to its derived class objects.
#include<iostream.h>#include<string.h> //Parent1.cpp: Invoking DC members through BC pointer
class Father // Father’s name
{ char name[20];
public: Father(char *fname)
{strcpy(name, fname); //fname contains Father’s name
} void show() {cout<<”Father’s name:” << name << endl;}};
class son: public Father{ char name[20]; // Son’s name
public: // 2 Argument constructor; invokes 1 argument constructor of Father
Son( char *sname, char *fname) : Father(fname)
{ strcpy(name, sname); // sname contains Son’s name }
void show() //show in derived class
{ cout<<”Son’s name:” << name << endl; }};
void main()
{ Father *fp; // pointer to Father’s class object
Father f1 ( “ RAVI”); fp = &f1; // fp points to Father class object
fp->show(); // Display Father show() function
Son s1 ( “ AMAN”, “RAVI”);
fp = &s1; // valid assignment
fp->show(); // guess what is output? Father or Son!
}
U4.85
Need For Virtual Functions�
U4.86
Pure virtual (abstract) functions and abstract base classes
C++ allows you to create a special kind of virtual function called a pure virtual function (or abstract function) that has no body at all! A pure virtual function simply acts as a placeholder that is meant to be redefined by derived classes.
A pure virtual function is a function that has the notation "= 0" in the declaration of that function.
class SomeClass
{
public:
virtual void pure_virtual() = 0; // a pure virtual function // note that there is no function body
};
U4.87
A pure virtual function can have an implementation in C++ – which is something that even many expert C++ developers do not know.
class SomeClass
{
public:
virtual void pure_virtual() = 0; // a pure virtual function // note that there is no function body };
/*This is an implementation of the pure_virtual function which is declared as a pure virtual function. This is perfectly legal: */
void SomeClass::pure_virtual()
{
cout<<"This is a test"<<endl;
}
U4.88
U4.89
class base�{public:�virtual void show()=0; //pure virtual function�};�class derived1 : public base�{public:�void show(){�cout<<"\n Derived 1";}};�class derived2 : public base�{�public:�void show()�{cout<<"\n Derived 2";}};���
void main()�{�base *b; derived1 d1; derived2 d2;�b = &d1;�b->show();�b = &d2;�b->show();�}
U4.90
Drawback of Virtual Function
U4.91
the *__vptr in each class points to the virtual table for that class. The entries in the virtual table point to the most-derived version of the function objects of that class are allowed to call.
So consider what happens when we create an object of type D1:
int main()
{
D1 cClass;
}
Because cClass is a D1 object, cClass has it’s *__vptr set to the D1 virtual table.
U4.92
Now, let’s set a base pointer to D1:
int main()
{
D1 cClass;
Base *pClass = &cClass;
}
So what happens when we try to call pClass->function1()?
int main()
{
D1 cClass;
Base *pClass = &cClass;
pClass->function1();
}
U4.93
int main()
{
Base cClass;
Base *pClass = &cClass;
pClass->function1();
}
U4.94
In this case, when cClass is created, __vptr points to Base’s virtual table, not D1′s virtual table. Consequently, pClass->__vptr will also be pointing to Base’s virtual table. Base’s virtual table entry for function1() points to Base::function1(). Thus, pClass->function1() resolves to Base::function1(), which is the most-derived version of function1() that a Base object should be able to call.
U4.95
How VPTR and Virtual table works(Memory Layout)
class Test
{
public:
int data1;
int data2;
int fun1();
};
int main()
{
Test obj;
cout << "obj's Size = " << sizeof(obj) << endl;
cout << "obj 's Address = " << &obj << endl;
return 0;
OUTPUT:
Sobj's Size = 4 Bytes�obj 's Address = 0012FF7C
Note: Any Plane member function does not take any memory.
U4.96
Example 2: Memory Layout of Derived class
class Test
{
public:
int a;
int b;
};
class dTest : public Test
{
public:
int c;
};
int main()
{
Test obj1;
cout << "obj1's Size = " << sizeof(obj1) << endl;
cout << "obj1's Address = " << &obj1 << endl;
dTest obj2;
cout << "obj2's Size = "<< sizeof(obj2) << endl;
cout << "obj2's Address = "<< &obj2 << endl;
return 0;
}
OUTPUT:�obj1's Size = 4�obj1's Address = 0012FF78�obj2's Size = 6�obj2's Address = 0012FF6C
U4.97
Example 3: Memory layout If we have one virtual function.
class Test
{
public:
int data;
virtual void fun1()
{
cout << "Test::fun1" << endl;
}
};
int main()
{
Test obj;
cout << "obj's Size = " << sizeof(obj) << endl;
cout << "obj's Address = " << &obj << endl;
return 0;
}
OUTPUT:
obj's Size = 4�obj's Address = 0012FF7C
Note: Adding one virtual function in a class takes 2 Byte extra.
U4.98
Example 4: More than one Virtual function
class Test
{
public:
int data;
virtual void fun1() { cout << "Test::fun1" << endl; }
virtual void fun2() { cout << "Test::fun2" << endl; }
virtual void fun3() { cout << "Test::fun3" << endl; }
virtual void fun4() { cout << "Test::fun4" << endl; }
};
int main()
{
Test obj;
cout << "obj's Size = " << sizeof(obj) << endl;
cout << "obj's Address = " << &obj << endl;
return 0;
}
U4.99
OUTPUT:
obj's Size = 4�obj's Address = 0012FF7C
Note: Adding more virtual functions in a class, no extra size taking i.e. Only one machine size taking(i.e. 2 byte)
U4.100
Multiple Inheritance
class Base1
{
public:
virtual void fun();
};
class Base2
{
public:
virtual void fun();
};
class Base3
{
public:
virtual void fun();
};
class Derive : public Base1, public Base2, public Base3
{
};
int main()
{
Derive obj;
cout << "Derive's Size = " << sizeof(obj) << endl;
return 0;
}
OUTPUT:
Derive's Size = 6
U4.101
in C++ a destructor is generally used to deallocate memory and do some other cleanup for a class object and it’s class members whenever an object is destroyed.
Example without a Virtual Destructor:
#include iostream.h
class Base
{
public:
Base()
{
cout<<"Constructing Base";
}
// this is a destructor:
~Base()
{
cout<<"Destroying Base";
}
};
U4.102
class Derive: public Base
{
public:
Derive()
{
cout<<"Constructing Derive";
}
~Derive(){
cout<<"Destroying Derive";
}
};
void main()
{
Base *basePtr = new Derive();
delete basePtr;
}
o/p-
Constructing Base
Constructing Derive
Destroying Base
we can see that the constructors get called in the appropriate order when we create the Derive class object pointer in the main function.
But there is a major problem with the code above: the destructor for the "Derive" class does not get called at all when we delete ‘basePtr’.
U4.103
what we can do is make the base class destructor virtual, and that will ensure that the destructor for any class that derives from Base (in our case, its the "Derive" class) will be called.
class Base
{
public:
Base()
{
cout<<"Constructing Base";
}
// this is a destructor:
virtual ~Base()
{
cout<<"Destroying Base";
}
};
o/p-
Constructing Base
Constructing Derive
Destroying Derive
Destroying Base
U4.104
Conclusion
U4.105
Working with Files
U4.106
Learning Objectives
U4.107
Learning Objectives
U4.108
Input/Output with Files
• C++ has support both for input and output
with files through the following classes:
• ofstream: File class for writing operations
(derived from ostream).
• ifstream: File class for reading operations
(derived from istream).
• fstream: File class for both reading and
writing operations (derived from iostream).
U4.109
Open a file
• First operation generally done on an object of one of these classes is to associate it to a real file.
• In order to open a file with a stream object, we use its member function open():
void open (const char * filename, openmode mode);
• where filename is a string of characters
representing the name of the file to be opened.
U4.110
Open a file Cont..
ios::in Open file for reading
ios::out Open file for writing
ios::ate Initial position: end of file
ios::app Every output is appended at the end of file.
ios::trunc If the file already existed it is erased.
ios::binary Binary mode
ofstreamfile;
file.open ("example.bin", ios::out | ios::app | ios::binary);
U4.111
Open a file (Cont..)
• Member functions open of classes
ofstream, ifstream and fstream include a
default mode.
Class Default Mode to Parameter
Ofstream ios::out | ios::trunc
Ifstream ios::in
Fstream ios::in | ios::out
U4.112
Open a file (Cont..)�
U4.113
Closing a File
void close();
U4.114
Text Mode Files
• Use the same members of these classes that we used in communication with the console.
// writing on a text file
#include <fstream.h>
int main () {
ofstream examplefile ("example.txt");
if (examplefile.is_open())
{examplefile << "This is a line.\n";
examplefile << "This is another line.\n";
examplefile.close();
}
return 0;}
U4.115
eof() Inherits from Class ios
// Reading a text file
#include <iostream.h>
#include <fstream.h>
#include <stdlib .h>
int main () {
char buffer[256];
ifstream examplefile ("example.txt");
if (! examplefile.is_open())
{ cout << "Error opening file";
exit (1); }
while (! examplefile.eof () )
{ examplefile.getline (buffer,100);
cout << buffer << endl; }
return 0;
}
U4.116
get and put Stream Pointers
All i/o streams objects have, at least, one stream
pointer:
• ifstream, has a pointer known as get pointer that points to the next element to be read.
• ofstream, has a pointer put pointer that points tot he location where the next element has to be written.
• Finally fstream, inherits both: get and put.
• These stream pointers that point to the reading or writing locations within a stream can be read and/or manipulated using the following member
functions:
U4.117
Functions for get & put pointers
• tellg() and tellp()
These two member functions admit no parameters and
return the current position of get stream pointer (in case
of tellg) or put stream pointer (in case of tellp).
• seekg() andseekp()
1. To change the position of stream pointers get and put. Both functions are overloaded with two different
prototypes:
seekg ( pos_type position );
seekp ( pos_type position );
The stream pointer is changed to an absolute position
from the beginning of the file.
U4.118
Functions for get & put pointers Cont..
• seekg ( off_type offset, seekdir direction );
seekp( off_type offset, seekdir direction );
• Using this prototype, an offset from a concrete
point determined by parameter direction can be
specified. It can be:
ios::beg offset specified from the beginning of the stream.
ios::cur offset specified from the current position of the stream pointer.
ios::end offset specified from the end of the stream.
U4.119
Obtaining File Size
#include <iostream.h>
#include <fstream.h>
const char * filename = "example.txt";
int main () {
long l,m;
ifstream file (filename, ios::in | ios::binary);
l = file.tellg();
file.seekg (0, ios::end);
m = file.tellg();
file.close();
cout << "size of " << filename;
cout << " is " << (m-l) << " bytes.\n";
return 0; }
U4.120
Binary Files
write (char *buffer, streamsize size);
read (char *buffer, streamsize size);
U4.121
Reading Writing Binary File
const char *filename=“example.txt”;
int main() {
char *buffer;
long size;
ifstream file (filename, ios::in | ios::binary | ios::ate);
size = file.tellg();
file.seekg(0, ios::beg);
buffer = new char [size];
U4.122
Reading Writing Binary File
file.read (buffer, size);
file.close();
cout<<“the complete file is in buffer”;
ofstream file1 (“test1.txt”, ios::out | ios :: binary);
file1.write (buffer, size);
delete[] buffer;
return 0; }
U4.123
get() and put()
• To read and write data
istream& get(char &ch)
ostream& put(char& ch)
while (in.get(ch))
cout<<ch;
for(i=0; i<256;i++)
out.put((char)i);
U4.124
Conclusion
U4.125
Exceptional Handling
U4.126
Learning Objectives
U4.127
Exception Handling�
U4.128
Exception Handling�
U4.129
Exception Handling Mechanisms�
U4.130
The catch block that catches an exception must immediately follow the try block that throws the exception.
Exception Handling Mechanisms
U4.131
The general form of these two blocks is as follows:
U4.132
Throw Mechanism
U4.133
Throw Mechanism
U4.134
Catch Mechanism �
U4.135
Catch Mechanism �
U4.136
Multiple Catch Statements
U4.137
Multiple Catch Statements
U4.138
Example : Program to illustrate multiple catch statements execution
U4.139
Multiple Catch Execution
U4.140
Re-throwing an Exception
throw;
U4.141
Program to illustrate re-throwing of exception
U4.142
Re-throwing an Exception
U4.143
Exception Specification �
U4.144
Exception Specification �
U4.145
Conclusion
U4.146
Review Questions [Objective Types]
U4.147
Review Questions [Short Answer Types]
U4.148
Review Questions [Short Answer Types]
U4.149
Review Questions [Long Answer Types]
U4.150
Review Questions [Long Answer Types]
U4.151
Review Questions [Long Answer Types]
U4.152