Unit 3
Constructors and Destructors
Constructors are functions of a class that are executed when new objects of the class are created. The constructors have the same name as the class and no return type, not even void. They are primarily useful for providing initial values for variables of the class.
The two main types of constructors are default constructors and parameterized constructors. Details about these are given as follows.
Default Constructors
Default constructors do not take any parameters. If a default constructor is not provided by the programmer explicitly, then the compiler provides a implicit default constructor. In that case, the default values of the variables are 0.
A program that demonstrates default constructors is given as follows.
Example
#include <iostream>
Using namespace std;
Class A {
Private:
Int num1, num2 ;
Public:
A() {
Num1 = 5;
Num2 = 7;
}
Void display() {
Cout<<"num1 = "<< num1 <<endl;
Cout<<"num2 = "<< num2 <<endl;
}
};
Int main() {
Aobj;
Obj.display();
Return 0;
}
Output
Num1 = 5
Num2 = 7
In the above program, the class A contains a default constructor that initialises num1 and num2 as 5 and 7. It also contains a function display() that prints the value of num1 and num2. The code snippet for this is given as follows.
Class A {
Private:
Int num1, num2 ;
Public:
A() {
Num1 = 5;
Num2 = 7;
}
Void display() {
Cout<<"num1 = "<< num1 <<endl;
Cout<<"num2 = "<< num2 <<endl;
}
};
The function main() contains the object definition for an object of class type A. Then the function display() is called. This is shown below.
Aobj;
Obj.display();
Parameterized Constructors
The parameterized constructors can take arguments to initialize an object when it is created. Parameters are added to a parameterized constructor just like they are added to a normal function. The parameterized constructors can be called implicitly or explicitly.
A program that demonstrates parameterized constructors is given as follows.
Example
#include <iostream>
Using namespace std;
Class A {
Private:
Int num1, num2 ;
Public:
A(int n1, int n2) {
Num1 = n1;
Num2 = n2;
}
Void display() {
Cout<<"num1 = "<< num1 <<endl;
Cout<<"num2 = "<< num2 <<endl;
}
};
Int main() {
A obj(3,8);
Obj.display();
Return 0;
}
Output
Num1 = 3
Num2 = 8
In the above program, the class A contains a parameterized constructor that initialises num1 and num2 with the values provided by n1 and n2. It also contains a function display() that prints the value of num1 and num2. The code snippet for this is given as follows.
Class A {
Private:
Int num1, num2 ;
Public:
A(int n1, int n2) {
Num1 = n1;
Num2 = n2;
}
Void display() {
Cout<<"num1 = "<< num1 <<endl;
Cout<<"num2 = "<< num2 <<endl;
}
};
The function main() contains the object definition for an object of class type A. Then the function display() is called. This is shown below.
A obj(3,8);
Obj.display();
The Class Constructor
A class constructor is a special member function of a class that is executed whenever we create new objects of that class.
A constructor will have exact same name as the class and it does not have any return type at all, not even void. Constructors can be very useful for setting initial values for certain member variables.
Following example explains the concept of constructor −
#include <iostream>
Using namespace std;
Class Line {
Public:
VoidsetLength( double len );
DoublegetLength( void );
Line(); // This is the constructor
Private:
Double length;
};
// Member functions definitions including constructor
Line::Line(void) {
Cout<< "Object is being created" <<endl;
}
Void Line::setLength( double len ) {
Length = len;
}
Double Line::getLength( void ) {
Return length;
}
// Main function for the program
Int main() {
Line line;
// set line length
Line.setLength(6.0);
Cout<< "Length of line : " <<line.getLength() <<endl;
Return 0;
}
When the above code is compiled and executed, it produces the following result −
Object is being created
Length of line : 6
Parameterized Constructor
A default constructor does not have any parameter, but if you need, a constructor can have parameters. This helps you to assign initial value to an object at the time of its creation as shown in the following example −
#include <iostream>
Using namespace std;
Class Line {
Public:
VoidsetLength( double len );
DoublegetLength( void );
Line(double len); // This is the constructor
Private:
Double length;
};
// Member functions definitions including constructor
Line::Line( double len) {
Cout<< "Object is being created, length = " <<len<<endl;
Length = len;
}
Void Line::setLength( double len ) {
Length = len;
}
Double Line::getLength( void ) {
Return length;
}
// Main function for the program
Int main() {
Line line(10.0);
// get initially set length.
Cout<< "Length of line : " <<line.getLength() <<endl;
// set line length again
Line.setLength(6.0);
Cout<< "Length of line : " <<line.getLength() <<endl;
Return 0;
}
When the above code is compiled and executed, it produces the following result −
Object is being created, length = 10
Length of line : 10
Length of line : 6
Using Initialization Lists to Initialize Fields
In case of parameterized constructor, you can use following syntax to initialize the fields −
Line::Line( double len): length(len) {
Cout<< "Object is being created, length = " <<len<<endl;
}
Above syntax is equal to the following syntax −
Line::Line( double len) {
Cout<< "Object is being created, length = " <<len<<endl;
Length = len;
}
If for a class C, you have multiple fields X, Y, Z, etc., to be initialized, then use can use same syntax and separate the fields by comma as follows −
C::C( double a, double b, double c): X(a), Y(b), Z(c) {
....
}
The Class Destructor
A destructor is a special member function of a class that is executed whenever an object of it's class goes out of scope or whenever the delete expression is applied to a pointer to the object of that class.
A destructor will have exact same name as the class prefixed with a tilde (~) and it can neither return a value nor can it take any parameters. Destructor can be very useful for releasing resources before coming out of the program like closing files, releasing memories etc.
Following example explains the concept of destructor −
#include <iostream>
Using namespace std;
Class Line {
Public:
VoidsetLength( double len );
DoublegetLength( void );
Line(); // This is the constructor declaration
~Line(); // This is the destructor: declaration
Private:
Double length;
};
// Member functions definitions including constructor
Line::Line(void) {
Cout<< "Object is being created" <<endl;
}
Line::~Line(void) {
Cout<< "Object is being deleted" <<endl;
}
Void Line::setLength( double len ) {
Length = len;
}
Double Line::getLength( void ) {
Return length;
}
// Main function for the program
Int main() {
Line line;
// set line length
Line.setLength(6.0);
Cout<< "Length of line : " <<line.getLength() <<endl;
Return 0;
}
When the above code is compiled and executed, it produces the following result −
Object is being created
Length of line : 6
Object is being deleted
- They should be declared in the public section.
- They are invoked automatically when the objects are created.
- They do not have return (data type) type not even void and there for they cannot return any values.
- They cannot be inherited, the a derived class can call the base class constructor.
- They make implicit calls to the operator new and delete when memory allocation is required.
- It is not possible to take the address of a constructor.
- An object of a class with a constructor cannot be a member of a union.
Note:-
Constructors and destructors have no return type, not even void.
A constructor for a class is needed so that the compiler automatically initializes an object as soon as it is created. A class constructor, if defined , is called whenever a program creates an object of that class.
In C++, constructor is a special method which is invoked automatically at the time of object creation. It is used to initialize the data members of new object generally. The constructor in C++ has the same name as class or structure.
There can be two types of constructors in C++.
- Default constructor
- Parameterized constructor
C++ Default Constructor
A constructor which has no argument is known as default constructor. It is invoked at the time of creating object.
Let's see the simple example of C++ default Constructor.
- #include <iostream>
- Using namespace std;
- Class Employee
- {
- Public:
- Employee()
- {
- Cout<<"Default Constructor Invoked"<<endl;
- }
- };
- Int main(void)
- {
- Employee e1; //creating an object of Employee
- Employee e2;
- Return 0;
- }
Output:
Default Constructor Invoked
Default Constructor Invoked
C++ Parameterized Constructor
A constructor which has parameters is called parameterized constructor. It is used to provide different values to distinct objects.
Let's see the simple example of C++ Parameterized Constructor.
#include <iostream>
Using namespace std;
Class Employee {
Public:
Int id;//data member (also instance variable)
String name;//data member(also instance variable)
Float salary;
Employee(inti, string n, float s)
{
Id = i;
Name = n;
Salary = s;
}
Void display()
{
Cout<<id<<" "<<name<<" "<<salary<<endl;
}
};
Int main(void) {
Employee e1 =Employee(101, "Sonoo", 890000); //creating an object of Employee
Employee e2=Employee(102, "Nakul", 59000);
e1.display();
e2.display();
Return 0;
}
Output:
101 Sonoo 890000
102 Nakul 59000
Overloaded constructors have the same name (name of the class) but the different number of arguments. Depending upon the number and type of arguments passed, the corresponding constructor is called.
Example 1: Constructor overloading
// C++ program to demonstrate constructor overloading
#include <iostream>
Using namespace std;
Class Person {
Private:
Int age;
Public:
// 1. Constructor with no arguments
Person() {
Age = 20;
}
// 2. Constructor with an argument
Person(int a) {
Age = a;
}
IntgetAge() {
Return age;
}
};
Int main() {
Person person1, person2(45);
Cout<< "Person1 Age = " << person1.getAge() <<endl;
Cout<< "Person2 Age = " << person2.getAge() <<endl;
Return 0;
}
Output
Person1 Age = 20
Person2 Age = 45
In this program, we have created a class Person that has a single variable age.
We have also defined two constructors Person() and Person(int a):
- When the object person1 is created, the first constructor is called because we have not passed any argument. This constructor initializes age to 20.
- When person2 is created, the second constructor is called since we have passed 45 as an argument. This constructor initializes age to 45.
The function getAge() returns the value of age, and we use it to print the age of person1 and person2.
Example 2: Constructor overloading
// C++ program to demonstrate constructor overloading
#include <iostream>
Using namespace std;
Class Room {
Private:
Double length;
Double breadth;
Public:
// 1. Constructor with no arguments
Room() {
Length = 6.9;
Breadth = 4.2;
}
// 2. Constructor with two arguments
Room(double l, double b) {
Length = l;
Breadth = b;
}
// 3. Constructor with one argument
Room(double len) {
Length = len;
Breadth = 7.2;
}
DoublecalculateArea() {
Return length * breadth;
}
};
Int main() {
Room room1, room2(8.2, 6.6), room3(8.2);
Cout<< "When no argument is passed: " <<endl;
Cout<< "Area of room = " << room1.calculateArea() <<endl;
Cout<< "\nWhen (8.2, 6.6) is passed." <<endl;
Cout<< "Area of room = " << room2.calculateArea() <<endl;
Cout<< "\nWhen breadth is fixed to 7.2 and (8.2) is passed:" <<endl;
Cout<< "Area of room = " << room3.calculateArea() <<endl;
Return 0;
}
Output
When no argument is passed:
Area of room = 28.98
When (8.2, 6.6) is passed.
Area of room = 54.12
When breadth is fixed to 7.2 and (8.2) is passed:
Area of room = 59.04
- When room1 is created, the first constructor is called. Length is initialized to 6.9 and breadth is initialized to 4.2.
- When room2 is created, the second constructor is called. We have passed the arguments 8.2 and 6.6. Length is initialized to the first argument 8.2 and breadth is initialized to 6.6.
- When room3 is created, the third constructor is called. We have passed one argument 8.2. Length is initialized to the argument 8.2. Breadth is initialized to the 7.2 by default.
The Dynamic Initialization of Objects means to initialize the data members of the class while creating the object. When we want to provide initial or default values to the data members while creating of object - we need to use dynamic initialization of objects.
Now, the question is how to achieve or implement dynamic initialization of objects?
It can be implemented by using parameterized constructors in C++.
Example:
Here, we have a class named "Student" which contains two private data members 1) rNo - to store roll number and 2) perc - to store percentage.
Program:
#include <iostream>
Usingnamespacestd;
//structure definition with private and public members
Struct Student {
Private:
IntrNo;
Float perc;
Public:
//constructor
Student(int r, float p)
{
RNo = r;
Perc = p;
}
//function to read details
Void read(void)
{
Cout<<"Enter roll number: ";
Cin>>rNo;
Cout<<"Enter percentage: ";
Cin>> perc;
}
//function to print details
Void print(void)
{
Cout<<endl;
Cout<<"Roll number: "<<rNo<<endl;
Cout<<"Percentage: "<< perc <<"%"<<endl;
}
};
//Main code
Intmain()
{
//reading roll number and percentage to initialize
//the members while creating object
Cout<<"Enter roll number to initialize the object: ";
Introll_number;
Cin>>roll_number;
Cout<<"Enter percentage to initialize the object: ";
Float percentage;
Cin>> percentage;
//declaring and initialize the object
Struct Student std(roll_number, percentage);
//print the value
Cout<<"After initializing the object, the values are..."<<endl;
Std.print();
//reading and printing student details
//by calling public member functions of the structure
Std.read();
Std.print();
Return0;
}
Output
Enter roll number to initialize the object: 101
Enter percentage to initialize the object: 84.02
After initializing the object, the values are...
Roll number: 101
Percentage: 84.02%
Enter roll number: 102
Enter percentage: 87
Roll number: 102
Percentage: 87%
A default argument is a value provided in a function declaration that is automatically assigned by the compiler if the caller of the function doesn’t provide a value for the argument with a default value.
Following is a simple C++ example to demonstrate the use of default arguments. We don’t have to write 3 sum functions, only one function works by using default values for 3rd and 4th arguments.
#include<iostream> Using namespace std;
// A function with default arguments, it can be called with // 2 arguments or 3 arguments or 4 arguments. Int sum(int x, int y, int z=0, int w=0) { Return (x + y + z + w); }
/* Driver program to test above function*/ Int main() { Cout<< sum(10, 15) <<endl; Cout<< sum(10, 15, 25) <<endl; Cout<< sum(10, 15, 25, 30) <<endl; Return 0; } |
Output:
25
50
80
When Function overloading is done along with default values. Then we need to make sure it will not be ambiguous.
The compiler will throw error if ambiguous. Following is the modified version of above program.
#include<iostream> Using namespace std;
// A function with default arguments, it can be called with // 2 arguments or 3 arguments or 4 arguments. Int sum(int x, int y, int z=0, int w=0) { Return (x + y + z + w); } Int sum(int x, int y, float z=0, float w=0) { Return (x + y + z + w); } /* Driver program to test above function*/ Int main() { Cout<< sum(10, 15) <<endl; Cout<< sum(10, 15, 25) <<endl; Cout<< sum(10, 15, 25, 30) <<endl; Return 0; } |
Error:
Prog.cpp: In function 'intmain()':
Prog.cpp:17:20: error: call of overloaded
'sum(int, int)' is ambiguous
Cout<< sum(10, 15) <<endl;
^
Prog.cpp:6:5: note: candidate:
Int sum(int, int, int, int)
Int sum(int x, int y, int z=0, int w=0)
^
Prog.cpp:10:5: note: candidate:
Int sum(int, int, float, float)
Int sum(int x, int y, float z=0, float w=0)
^
Key Points:
- Default arguments are different from constant arguments as constant arguments can't be changed whereas default arguments can be overwritten if required.
- Default arguments are overwritten when calling function provides values for them. For example, calling of function sum(10, 15, 25, 30) overwrites the value of z and w to 25 and 30 respectively.
- During calling of function, arguments from calling function to called function are copied from left to right. Therefore, sum(10, 15, 25) will assign 10, 15 and 25 to x, y, and z. Therefore, the default value is used for w only.
- Once default value is used for an argument in function definition, all subsequent arguments to it must have default value. It can also be stated as default arguments are assigned from right to left. For example, the following function definition is invalid as subsequent argument of default variable z is not default.
// Invalid because z has default value, but w after it // doesn't have default value Int sum(int x, int y, int z=0, int w) |
Symbolic constant is a way of defining a variable constant whose value cannot be changed. It is done by using the keyword const.
For example
constint c=5;
In C symbolic constant can be achieved by the use of #define.
For example,
#define PI=3.142;
When this statement is compiled, the pre-processor(#) will replace all the occurrence of PI with 3.142, which is then compiled into executable format.
A problem with this was the we cannot use any normal variable with same name PI throughout the program otherwise it will be replaced by its constant value. So this problem is solved in C++, by the use of const qualifier. The scoping of const values differs. A const in C++ is default to the internal linkage and therefore, it is local to the file where is is declared. While in C, constants values are global in nature. They are visible outside the file which they are declared. They can be made local by declaring them as static. To access the const value from another file we must explicitly define it as extern in C++.
For example
extern const total=100;
Symbolic constant can also be defined using enumeration.
For example,
enum{n1,n2};
The enumerator n1 and n2 can be assigned constant value in following way:
const n1=1;
const n2=70;
A destructor works opposite to constructor; it destructs the objects of classes. It can be defined only once in a class. Like constructors, it is invoked automatically.
A destructor is defined like constructor. It must have same name as class. But it is prefixed with a tilde sign (~).
Note: C++ destructor cannot have parameters. Moreover, modifiers can't be applied on destructors.
C++ Constructor and Destructor Example
Let's see an example of constructor and destructor in C++ which is called automatically.
- #include <iostream>
- Using namespace std;
- Class Employee
- {
- Public:
- Employee()
- {
- Cout<<"Constructor Invoked"<<endl;
- }
- ~Employee()
- {
- Cout<<"Destructor Invoked"<<endl;
- }
- };
- Int main(void)
- {
- Employee e1; //creating an object of Employee
- Employee e2; //creating an object of Employee
- Return 0;
- }
Output:
Constructor Invoked
Constructor Invoked
Destructor Invoked
Destructor Invoked
|
- If a destructor is present, rewrite that to be the class finalizer.
- If a Dispose() method is present, rewrite that into the class destructor.
- If a destructor is present but there is no Dispose() method, retain the destructor while carrying out the first item.
In moving your code from Managed Extensions to the new syntax, it is possible to miss performing this transformation. If the application depended in some way on the execution of associated finalization methods, then the behavior of the application will silently differ.
Destructors and Finalizers
Destructors in a reference type perform deterministic clean up of your resources. Finalizers clean up unmanaged resources and can be called deterministically by the destructor or non-deterministically by the garbage collector.
Classclassname
{
~classname() {} // destructor
!classname() {} // finalizer
};
Parameters | |
Classname | The name of the class for which you are creating the destructor or finalizer. |
|
The behavior of destructors in a managed C++ class differs from the behavior in previous releases. The common language runtime's garbage collector deletes unused managed objects and releases their memory when no longer needed. However, a type may use resources that the garbage collector does not know how to release. These resources are known as unmanaged resources (native file handles, for example). You should release all unmanaged resources in the finalizer. Because managed resources are released non-deterministically by the garbage collector, it is not safe to refer to managed resources in a finalizer because it is possible that the garbage collector has already cleaned up that managed resource.
A Visual C++ finalizer is not the same as the Finalize() method (common language runtime documentation uses finalizer and the Finalize() method synonymously). The Finalize() method is called by the garbage collector, which invokes each finalizer in a class inheritance chain. Unlike Visual C++ destructors, calling a derived class finalizer does not cause the compiler to invoke call the finalizer in all base classes. Because the Visual C++ compiler provides support for deterministic release of resources, Visual C++ programmers should not attempt to implement the Dispose() or Finalize() methods. However, if you are familiar with implementing these methods, this is how a Visual C++ finalizer and a destructor that calls the finalizer maps to the Dispose() pattern.
// C++ code
Ref class T
{
~T() { this->!T(); } // destructor calls finalizer
!T() {} // finalizer
};
// equivalent Dispose pattern
Void Dispose(bool disposing)
{
If (disposing)
{
~T();
}
Else
{
!T();
}
}
A managed type may also use managed resources that you would prefer to release deterministically, and not leave to the garbage collector to release at some point after the object is no longer needed (non-deterministically). Deterministically releasing resources can significantly improve performance. The Visual C++ compiler lets you define a destructor to deterministically clean up objects. All resources that you want to deterministically release should be released in the destructor. If a finalizer is present, you should call your type's finalizer from the destructor, to avoid code duplication.
// destructors_finalizers_1.cpp
// compile with: /clr /c
Refstruct A
{
// destructor cleans up all resources
~A()
{
// clean up code to release managed resource
// ...
// to avoid code duplication
// call finalizer to release unmanaged resources
This->!A();
}
// finalizer cleans up unmanaged resources
// destructor or garbage collector will
// clean up managed resources
!A()
{
// clean up code to release unmanaged resource
// ...
}
};
If the code consuming your type does not call the destructor, the garbage collector will eventually release all managed resources. The presence of a destructor does not imply the presence of a finalizer. However, a finalizer implies that you will define a destructor, and call the finalizer from the destructor. This provides for the deterministic release of unmanaged resources. Calling the destructor will suppress (with SuppressFinalize()) finalization of the object. If the destructor is not called, your type's finalizer will eventually be called by the garbage collector.
Deterministically cleaning up your object's resources by calling the destructor can increase performance compared with letting the common language runtime non-deterministically finalize the object. Code authored in Visual C++ and compiled with /clr will run a type's destructor for the following reasons:
- If an object created using stack semantics goes out of scope.
- If an exception is thrown during the object's construction.
- If the object is a member in an object whose destructor is running.
- If you call the delete operator (C++) on a handle (^ (Handle to object on Managed Heap)).
- If you explicitly call the destructor.
If your type is being consumed by a client authored in another language, the destructor will be called when:
- A call to Dispose().
- Calling Dispose(void) on the type.
- If the type goes out of scope in a C# using statement.
If you create an object of a reference type on the managed heap (not using stack semantics for reference types), use try/finally syntax (try-finally statement) to ensure that an exception does not prevent the destructor from running:
// clr destructors example
// compile with: /clr
#include "stdafx.h"
Using namespace System;
Refstruct A
{
~A() {}
};
Int main()
{
A ^ MyA = gcnew A;
Try
{
// use MyA
}
Finally
{
DeleteMyA;
}
Return 0;
}
Output: None
If your type has a destructor, the compiler will generate a Dispose() method that implements IDisposable. If a type authored in C++ with a destructor is consumed from another language, calling IDisposable::Dispose on that type will cause the type's destructor to be called. When consumed from a C++ client, you cannot directly call Dispose(); call the destructor instead using the delete operator. If your type has a finalizer, the compiler will generate a Finalize(void) method that overrides Finalize(). If a type has either a finalizer or destructor. The compiler will generate a Dispose(bool) method, according to the design pattern. You cannot explicitly author or call Dispose(bool) in Visual C++. If a type has a base class that conforms to the design pattern, the destructors for all base classes will be called when the destructor for the derived class is called. If your type is authored in C++, the compiler will ensure that your types implement this pattern. That is, the destructor of a reference class will chain to its bases and members as specified by the C++ standard (first the classes’ destructor is run, then the destructors for its members in the reverse order they were constructed, and finally the destructors for its base classes in the reverse order they were constructed).
Destructors and finalizers are not allowed inside value types or interfaces. A finalizer can only be defined or declared in a reference type. Like a constructor and destructor, a finalizer has no return type. After an object's finalizer runs, finalizers in any base classes will also be called, beginning with the least derived type. Finalizers for data members are not automatically chained to by a class’s finalizer. If a finalizer deletes a native pointer in a managed type you will need to ensure that references to or through the native pointer are not prematurely collected; call the destructor on the managed type instead of using KeepAlive. You can detect at compile time if a type has a finalizer or destructor.
Program Example
This sample shows two types, one with unmanaged resources and one with managed resources that are deterministically released.
// destructors and finalizers
// compile with: /clr
#include "stdafx.h"
#include <vcclr.h>
#include <stdio.h>
Using namespace System;
Using namespace System::IO;
Ref class SystemFileWriter
{
FileStream ^ file;
Array<Byte> ^ arr;
IntbufLen;
Public:
SystemFileWriter(String ^ name) : file(File::Open(name, FileMode::Append)),
Arr(gcnew array<Byte>(1024)) {}
Void Flush()
{
File->Write(arr, 0, bufLen);
BufLen = 0;
}
~SystemFileWriter()
{
Flush();
Delete file;
}
};
Ref class CRTFileWriter
{
FILE * file;
Array<Byte> ^ arr;
IntbufLen;
Static FILE * getFile(String ^ n)
{
Pin_ptr<constwchar_t> name = PtrToStringChars(n);
FILE * ret = 0;
_wfopen_s(&ret, name, L"ab");
Return ret; }
Public:
CRTFileWriter(String ^ name) : file(getFile(name)), arr(gcnew array<Byte>(1024)) {}
Void Flush()
{
Pin_ptr<Byte>buf = &arr[0];
Fwrite(buf, 1, bufLen, file);
BufLen = 0;
}
~CRTFileWriter()
{
This->!CRTFileWriter();
}
!CRTFileWriter()
{
Flush();
Fclose(file);
}
};
Int main()
{ SystemFileWriterwri("systest.txt");
CRTFileWriter ^ wri2 = gcnewCRTFileWriter("crttest.txt");
Return 0;
}
Output: None
References:
1. Object-Oriented Programming and Java by Danny Poo (Author), Derek Kiong (Author), Swarnalatha Ashok (Author)Springer; 2nd ed. 2008 edition (12 October 2007), ISBN-10: 1846289629, ISBN-13: 978-1846289620,2007
2. Java The complete reference, 9th edition, Herbert Schildt, McGraw Hill Education (India) Pvt. Ltd.
3. Object-Oriented Design Using Java, Dale Skrien, McGraw-Hill Publishing, 2008, ISBN - 0077423097, 9780077423094. 4. UML for Java Programmers by Robert C. Martin, Prentice Hall, ISBN 0131428489,2003.