0% found this document useful (0 votes)
202 views21 pages

Q-1: Explain The Concept of Constructers and Destructors in C+ + With Programming Examples

Constructors and destructors are special member functions in C++ that are automatically called when objects are created and destroyed. Constructors initialize object data members and are called when an object is created, while destructors perform cleanup tasks and are called when an object is destroyed. The document provides examples of constructor and destructor definitions and calls in a Sample class. It also discusses overloaded constructors and the differences between constructors and destructors.

Uploaded by

Chander Shekhar
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
202 views21 pages

Q-1: Explain The Concept of Constructers and Destructors in C+ + With Programming Examples

Constructors and destructors are special member functions in C++ that are automatically called when objects are created and destroyed. Constructors initialize object data members and are called when an object is created, while destructors perform cleanup tasks and are called when an object is destroyed. The document provides examples of constructor and destructor definitions and calls in a Sample class. It also discusses overloaded constructors and the differences between constructors and destructors.

Uploaded by

Chander Shekhar
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 21

February 2010

Master of Computer Application (MCA) –


Semester 2
MC0066 – OOPS using C++
Assignment Set – 2
Q-1: explain the concept of constructers and destructors in c+
+ with Programming examples.
Constructor & Destructors: constructors and destructors are very
important components of a class. Constructors are member functions
of a class which have same name as the class name. Constructors are
called automatically whenever an object of

The class is created. This feature makes it very useful to initialize the
class data members whenever a new object is created. It also can
perform any other function that needs to be performed for all the
object of the class without explicitly specifying it.

Destructors on the other hand are also member functions with the
same name as class but are prefixed with tilde (~) sign to differentiate it
from the constructor. They are invoked automatically whenever the
object’s life expires or it is destroyed. It can be used to return the
memory back to the operating system if the memory was dynamically
allocated. We will see dynamic allocation of memory in unit 7 while
discussing pointers.

// constdest .cpp

# include<iostream.h>
Class sample

Private:

Int data;

Public:

Sample ( ) { data = 0; cout<<”constructor invoked”<<endl ;}

~ Sample ( ) {cout<<destructor invoked” ;}

Void display ( )

{ cout <<” data<<” <<data<<endl ;}

};

Void main( )

{ sample obj1;

Obj.display ( );

When object of sample class, obj is created, automatically the


constructor is invoked and data is initialized to zero. When the object is
destroyed which invokes the destructor. Please note that both the
constructor and destructor is declared as public and they have no
return value. However, constructors can have arguments

And can be overloaded so that different constructors can be called


depending upon the arguments that is passed. Destructors on the other
hand cannot be overloaded and cannot have any arguments. The
following program implements the overloaded constructors for the
distance class.

In the above program, the set distance function is replaced with the
two constructor. These are automatically invoked. When object d1 is
created the first constructor distance ( ) is invoked. When object d2 is
created the second constructor distance (int f, int i) is invoked as two
arguments are passed. Please note that to invoke a constructor with
arguments, argument values have to be passed along with the object
name during declaration.

1. Explain the concept of operator overloading with


suitable examples for each.
Ans –
Operator overloading is an interesting feature of C++ that allows programmers to
specify how various arithmetic, relational and many other operators work with user defined
datatypes or classes. It provides a flexible way to work with classes and can make program
code look obvious. In the unit 5, we had written an add function for the class distance. To
perform addition of two distance objects we used a call d3.add(d1,d2). Instead of such
statements it would be more clear if we could use statements like d3=d1+d2. This is
possible only if we inform compiler about how + operator works with distance class. This is
exactly what operator overloading feature in C++ does. It helps to use the default operators
with the user defined objects for making the code simpler.
However there are several problems with operator overloading which you should be
aware of. When using operator overloading, the operator should perform only the most
obvious function. Otherwise it will lead to more confusion. If you are overloading + operator
for distance class it should add two distance objects, and should not do something else.
However some syntactical characteristics of operators cannot be changed even if you want
to. For example, you cannot overload a binary operator to be a unary operator and vice
versa.
Several operators such as dot operator, scope resolution (::)
operator, conditional operator (?:) etc cannot be overloaded.
Therefore operator overloading should be used for a class where it is required to
perform obvious functions with the default operators and there can be no other meaning for
the same.

2. Describe the following:


a) Types of Inheritance
Ans –
·Inheritance is a very powerful feature of object oriented programming. It allows
reuse of code without modifying the original code. It also allows flexibility to programmer to
make modifications to the program without altering the original code which saves debugging
and programming time and effort.
Inheritance feature has enabled to distribute class libraries which allows the
programmer to use the standard code developed by some another company. Inheritance is
the process of creating new classes known as derived classes from the existing or base
class. The features of the base class are said to be inherited by the derived class. The child
class has all the functionality of the parent class and has additional functionalities of its own.
The data members in a class are usually declared private. But if the class will be
inherited by another class, then data members that will be inherited will have to be declared
as protected. Protected access specifier allows data members to be accessed by the
member functions of inherited class but does not allow to be accessed from external
programs. Private members cannot be accessed by the inherited class member functions.
The accessibilty of base class members are also dependent on the type of inheritance:
private or public. The public inheritance is commonly used which is shown in the program
inheritance.cpp discussed next. The types of inheritance are discussed in the next section.
Hierarchial Inheritance
several classes derived from a single base class
Multilevel Inheritance
Inheritance can also be multilevel inheritance where another class is derived from the
derived class. In such case the grand child class inherits all the properties of child and
parent classes.

Multiple Inheritance
The derived class can also have multiple parents which is known as multiple inheritance.
Here the child or derived class has two or more parent classes. The child class inherits all
the properties of all its parents. Multiple inheritance is implemented same as single
inheritance except that both the parent names have to be specified while defining the class.
We will discuss multiple inheritance in detail in the next unit.
In the above example we have created a class employee and a student. Manager class is
defined from both of these classes. This is useful in instances when you want to create an
employee whose educational qualifications need not be stored such as a worker.

b) Objects and Pointers


Ans –
Pointers can point to userdefined objects as well. If we would like to define a pointer to an

object of class employee, we would use the following statement:

employee *ptr;

where ptr is a pointer pointing to object of employee class.


To access the member functions through the pointer there is simple operator -> which is known as
membership access operator. This can be used instead of dot operator when using pointers to
access the member data or functions.
The following statement accesses member function display of the employee class through
the pointer ptr:
ptr->display();
Another important use of pointers is creating datastructures like linked list. Linked list is a dynamic
data structure which can be imagined as set of nodes. Every node stores data and link to the next
node in the list. The following example implements the node using a structure and linklist using class
that stores pointer to the first node in the list.
//linklist.cpp
# include<iostream.h>
# include<conio.h>

struct node
{int data;
node* next; // pointer to next node
};
class list
{ private:
node *first; // pointer to the first node in the list
public:
list() // no-argument default constructor
{ first=NULL;} // empty list : no first node
void additem(int d) // adds new node to the beginning of the list
{node* newnode; // node pointer
newnode = new node; // create a new node
newnode->data=d; //assign value
newnode->next=first; // assign pointer to the first
first=newnode; // first now points to new node
}void display() // displays all nodes
{ node* temp; // pointer to node
temp=first;
while (temp!=NULL)
{ cout<< endl<<temp->data; // print data
temp=temp->next; // points to next node
}}};
void main()
{ clrscr();
list list1;
list1.additem(25);
list1.additem(50);
list1.additem(52);
list1.display();
getch();
}Every object created has a unique pointer created by default known as this pointer.This
pointer is a default pointer created for every object that points to the object itself. All the member
functions have access to “this pointer”. It is useful to return the object itself after modification. The
following program shows the use of this pointer to overload assignment operator =:
# include<iostream.h>
class alpha
{ private:
int data;
public:
alpha() {data=0;}

alpha (int d) {data=d;}


alpha& operator = (alpha& a)
{ data= a.data;
return *this;}
};
void main()
{alpha a1(37), a2;
a2=a1;
a2.display();
}

3. Describe the theory behind Virtual Functions and


Polymorphism along with suitable programming
examples for each.
Ans –
Virtual Functions
By default, C++ matches a function call with the correct function definition at compile
time. This is called static binding. You can specify that the compiler match a function call
with the correct function definition at run time; this is called dynamic binding. You declare a
function with the keywordvirtual if you want the compiler to use dynamic binding for that
specific function.
The following examples demonstrate the differences between static and
dynamic binding. The first example demonstrates static binding:
#include <iostream>
using namespace std;
struct A {
void f() { cout << "Class A" << endl; }
};
struct B: A {
void f() { cout << "Class B" << endl; }
};
void g(A& arg) {
arg.f();
}int main() {
B x;
g(x);
}The following is the output of the above example:
Class A

When functiong() is called, functionA: : f() is called, although the argument refers to an object
of typeB. At compile time, the compiler knows only that the argument of functiong() will be a
reference to an object derived fromA; it cannot determine whether the argument will be a
reference to an object of typeA or typeB. However, this can be determined at run time. The
following example is the same as the previous example, except thatA: : f() is declared with
thevi rtual keyword:
#include <iostream>
using namespace std;
struct A {
virtual void f() { cout << "Class A" << endl; }
};
struct B: A {
void f() { cout << "Class B" << endl; }
};
void g(A& arg) {
arg.f();
}int main() {
B x;
g(x);
}The following is the output of the above example:
Class BThevirtual keyword indicates to the compiler that it should choose
the appropriate definition off() not by the type of reference, but by the
type of object that the reference refers to.
Therefore, a virtual function is a member function you may redefine for other derived
classes, and can ensure that the compiler will call the redefined virtual function for an object
of the corresponding derived class, even if you call that function with a pointer or reference
to a base class of the object.
A class that declares or inherits a virtual function is called a polymorphic
class.
You redefine a virtual member function, like any member function, in any derived
class. Suppose you declare a virtual function named f in a classA, and you derive directly or
indirectly fromA a class namedB. If you declare a function namedf in classB with the same
name and same parameter list asA::f, thenB::f is also virtual (regardless whether or not you
declareB::f with thevirtual keyword) and it overridesA::f. However, if the parameter lists ofA::f
andB: : f are different,A::f andB: : f are considered different,B :: f does not overrideA::f, andB: : f
is not virtual (unless you have

declared it with thevirtual keyword). InsteadB ::f hidesA::f. The following


example demonstrates this:
#include <iostream>
using namespace std;
struct A {
virtual void f() { cout << "Class A" << endl; }
};
struct B: A {
void f(int) { cout << "Class B" << endl; }
};
struct C: B {
void f() { cout << "Class C" << endl; }
};
int main() {
B b; C c;
A* pa1 = &b;
A* pa2 = &c;
// b.f();
pa1->f();
pa2->f();
}The following is the output of the above example:
Class A
Class CThe functionB::f is not virtual. It hidesA::f. Thus the compiler will
not allow the function callb.f(). The functionC:: f is virtual; it overridesA::f
even thoughA::f is not visible inC.
If you declare a base class destructor as virtual, a derived class destructor will
override that base class destructor, even though destructors are not inherited.
The return type of an overriding virtual function may differ from the return type of the
overridden virtual function. This overriding function would then be called a covariant virtual
function. Suppose that
B::f overrides the virtual function A::f. The return types of A::fand B::fma y
differ if all the following conditions are met:
· The functionB::f returns a reference or pointer to a class of type T, and
A::f returns a pointer or a reference to an unambiguous direct or indirect
base class ofT.
· The const or volatile qualification of the pointer or reference returned byB :: f has the same
or less const or volatile qualification of the pointer or reference returned byA::f.

· The return type ofB ::f must be complete at the point of declaration of
B::f, or it can be of type B.
The following example demonstrates this:
#include <iostream>
using namespace std;
struct A { };
class B : private A {
friend class D;
friend class F;
};
A global_A;
B global_B;
struct C {
virtual A* f() {
cout << "A* C::f()" << endl;
return &global_A;
}};
struct D : C {
B* f() {
cout << "B* D::f()" << endl;
return &global_B;
}};
struct E;
struct F : C {
// Error:
// E is incomplete
// E* f();
};
struct G : C {
// Error:
// A is an inaccessible base class of B
// B* f();
};
int main() {
D d;
C* cp = &d;
D* dp = &d;
A* ap = cp->f();
B* bp = dp->f();
};

The following is the output of the above example:

B* D::f()

B* D::f()

The statement A* ap = cp->f() callsD: : f() and converts the pointer returned to typeA*. The
statement B* bp = dp->f() callsD::f() as well but does not convert the pointer returned; the type
returned isB*. The compiler would not allow the declaration of the virtual function F ::f()
becauseE is not a complete class. The compiler would not allow the declaration of the
virtual functionG::f() because classA is not an accessible base class of B (unlike friend
classesD andF, the definition ofB does not give access to its members for classG).
A virtual function cannot be global or static because, by definition, a virtual function is a
member function of a base class and relies on a specific object to determine which
implementation of the function is called. You can declare a virtual function to be a friend of
another class.
If a function is declared virtual in its base class, you can still access it directly using the
scope resolution (::) operator. In this case, the virtual function call mechanism is suppressed
and the function implementation defined in the base class is used. In addition, if you do not
override a virtual member function in a derived class, a call to that function uses the function
implementation defined in the base class.

A virtual function must be one of the following:

· Defined

· Declared pure

· Defined and declared pure


A base class containing one or more pure virtual member functions is
called an abstract class.
Polymorphism
In simple terms,polymor phis m lets you treat derived class members just
like their parent class’s members.
More precisely, polymorphism is the ability of objects belonging to different types to respond
to method calls of methods of the same name, each one according to an appropriate type-
specific behavior. The programmer (and the program) does not have to know the exact type
of the object in advance, so this behavior can be implemented at run time (this is called late
binding or dynamic binding).
The different objects involved only need to present a compatible interface to the clients (the
calling routines). That is, there must be public methods with the same name and the same
parameter sets in all the objects. In principle, the object types may be unrelated, but since
they share a common interface, they are often implemented as

subclasses of the same parent class. Though it is not required, it is understood that the
different methods will also produce similar results (for example, returning values of the
same type).
In practical terms, polymorphism means that if class B inherits from class A, it doesn’t have
to inherit everything about class A; it can do some of the things that class A does differently.
This means that the same “verb” can result in different actions as appropriate for a specific
class, so controlling code can issue the same command to a series of objects and get
appropriately different results from each one.
Polymorphism allows client programs to be written based only on the abstract interfaces of
the objects which will be manipulated (interface inheritance). This means that future
extension in the form of new types of objects is easy, if the new objects conform to the
original interface. In particular, with object-oriented polymorphism, the original client
program does not even need to be recompiled (only relinked) in order to make use of new
types exhibiting new (but interface-conformant) behavior.
(In C++, for instance, this is possible because the interface definition for a class defines a
memory layout, the virtual function table describing where pointers to functions can be
found. Future, new classes can work with old, precompiled code because the new classes
must conform to the abstract class interface, meaning that the layout of the new class’s
virtual function table is the same as before; the old, precompiled code can still look at the
same memory offsets relative to the start of the object’s memory in order to find a pointer to
the new function. It is only that the new virtual function table points to a new implementation
of the functions in the table, thus allowing new, interface-compliant behavior with old,
precompiled code.)
Consider the following example:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Animal {
public:
Animal(const string & name) : name(name) { }
virtual ~Animal() { }
virtual const string talk() = 0;
const string name;
};
class Cat : public Animal {
public:
Cat(const string & name) : Animal(name) { }
virtual ~Cat() { }
virtual const string talk() { return "Meow!"; }

};
class Dog : public Animal {
public:
Dog(const string & name) : Animal(name) { }
virtual ~Dog() { }
virtual const string talk() { return "Arf! Arf!"; }
};
// prints the following:
//
// Missy: Meow!
// Mr. Bojangles: Meow!
// Lassie: Arf! Arf!
int main() {
Animal * animals [] = {
new Cat("Missy"),
new Cat("Mr. Bojangles"),
new Dog("Lassie")
};
for(int i = 0; i < 3; i++)
cout << animals[i]->name << ": " << animals[i]->talk() << endl;
for(int i = 0; i < 3; i++)
delete animals[i];
return 0;
}Note that thetalk() method is explicitly declared asvirtual. This is because
polymorphic method calls have relatively high overhead in C++. This overhead is lessened
by treating all method calls as non-polymorphic, unless explicitly marked asvi rtual by the
developer.
4. Write a program in C++ demonstrating various file
handling techniques.
Ans –
#include<iostream.h>
#include<fstream.h>
#include<conio.h>
#include<stdio.h>
#include<process.h>
#include<string.h>
struct student
{ int rollno;
char name[20];
int marks;
}s;

void main()
{ ifstream fin;
ofstream fout;
int ch,no;
do
{ clrscr();
cout<<"\nMenu\n";
cout<<"\n1. Add";
cout<<"\n2. Search";
cout<<"\n3. Display";
cout<<"\n4. Exit";
cout<<"\n\nEnter your choice: ";cin>>ch;
switch(ch)
{ case 1:
{ cout<<"\nEnter rollno. :";cin>>s.rollno;
cout<<"\nName: ";gets(s.name);
cout<<"\nMarks: ";cin>>s.marks;
fout.open("student.dat",ios::binary|ios::app);
fout.write((char*)&s,sizeof(student));
fout.close();
break;
}case 2:
{ cout<<"\nEnter rollno. to be searched: ";cin>>no;
fin.open("student.dat",ios::binary|ios::in);
while(!fin.eof())
{ fin.read((char*)&s,sizeof(student));
if (s.rollno==no)
{ cout<<"\nRollno: "<<s.rollno;
cout<<"\nName: "<<s.name;
cout<<"\nMarks: "<<s.marks;
getch();
break;
}
}fin.close();
break;
}case 3:
{ fin.open("student.dat",ios::binary|ios::in);
while(!fin.eof())
{ clrscr();
fin.read((char*)&s,sizeof(student));

cout<<"\nRoll No. :"<<s.rollno;


cout<<"\nName: "<<s.name;
cout<<"\nMarks: "<<s.marks;
getch();
}fin.close(); break;
}case 4:exit(0);
} while (ch<=4);
}
5. Write about the following with the help of suitable
programming examples:
A) Throwing an Exception
B) Catching an
Exception
Ans –
Throwing an Exception
If you encounter an exceptional situation in your code – that is, one where you don’t have
enough information in the current context to decide what to do – you can send information
about the error into a larger context by creating an object containing that information and
“throwing” it out of your current context. This is called throwing an

exception. Here’s what it looks like:

throw myerror(“something bad happened”);

myerror is an ordinary class, which takes a char* as its argument. You


can use any type when you throw (including built-in types), but often you’ll use special types
created just for throwing exceptions. The keywordthrow causes a number of relatively
magical things to happen. First it creates an object that isn’t there under normal program
execution, and of course the constructor is called for that object. Then the object is, in
effect, “returned” from the function, even though that object type isn’t normally what the
function is designed to return.
A simplistic way to think about exception handling is as an alternate return mechanism,
although you get into trouble if you take the analogy too far – you can also exit from
ordinary scopes by throwing an exception. But a value is returned, and the function or
scope exits. Any similarity to function returns ends there becausewhere you return to is
someplace completely different than for a normal function call. (You end up in an
appropriate exception handler that may be miles away from

where the exception was thrown.) In addition, only objects that were successfully created at
the time of the exception are destroyed (unlike a normal function return that assumes all the
objects in the scope must be destroyed). Of course, the exception object itself is also
properly cleaned up at the appropriate point. In addition, you can throw as many different
types of objects as you want. Typically, you’ll throw a different type for each different type of
error. The idea is to store the information in the object and thetype of object, so someone in
the bigger context can figure out what to do with your exception.
Catching an Exception
If a function throws an exception, it must assume that exception is caught and dealt with. As
mentioned before, one of the advantages of C++ exception handling is that it allows you to
concentrate on the problem you’re actually trying to solve in one place, and then deal with
the errors from that code in another place.
Thetry block
If you’re inside a function and you throw an exception (or a called function throws an
exception), that function will exit in the process of throwing. If you don’t want athrow to leave
a function, you can set up a special block within the function where you try to solve your
actual programming problem (and potentially generate exceptions). This is called the try
block because you try your various function calls there. The try block is an ordinary scope,
preceded by the keywordtry:

try {

// Code that may generate exceptions

}If you were carefully checking for errors without using exception
handling, you’d have to surround every function call with setup and test code, even if you
call the same function several times. With exception handling, you put everything in a try
block without error checking. This means your code is a lot easier to write and easier to
read because the goal of the code is not confused with the error checking.
Exception handlers
Of course, the thrown exception must end up someplace. This is the
exception handler, and there’s one for every exception type you want to
catch. Exception handlers immediately follow the try block and are
denoted by the keywordca tch:

try {
// code that may generate exceptions
} catch(type1 id1) {
// handle exceptions of type1
} catch(type2 id2) {
// handle exceptions of type2
}// etc…
Each catch clause (exception handler) is like a little function that takes a single argument of
one particular type. The identifier (id1, id2, and so on) may be used inside the handler, just
like a function argument, although sometimes there is no identifier because it’s not needed
in the handler – the exception type gives you enough information to deal with it.
The handlers must appear directly after the try block. If an exception is thrown, the
exception handling mechanism goes hunting for the first handler with an argument that
matches the type of the exception. Then it enters that catch clause, and the exception is
considered handled. (The search for handlers stops once the catch clause is finished.) Only
the matching catch clause executes; it’s not like a switch statement where you need a break
after each case to prevent the remaining ones from executing. Notice that, within the try
block, a number of different function calls might generate the same exception, but you only
need one handler.

6. Write about the following with the help of suitable


programming examples:
A) Uncaught Exceptions
B) Standard
Exceptions
Ans –
Uncaught Exceptions
If none of the exception handlers following a particulartry block matches an exception, that
exception moves to the next-higher context, that is, the function ortry block surrounding
thetry block that failed to catch the exception. (The location of this higher-contexttry block is
not always obvious at first glance.) This process continues until, at some level, a handler
matches the exception. At that point, the exception is considered “caught,” and no further
searching occurs.
If no handler at any level catches the exception, it is “uncaught” or “unhandled.” An
uncaught exception also occurs if a new exception is thrown before an existing exception
reaches its handler – the most

common reason for this is that the constructor for the exception object
itself causes a new exception.
terminate()
If an exception is uncaught, the special functionterminate() is automatically called.
Likeunexpected(), terminate is actually a pointer to a function. Its default value is the
Standard C library functionabort(), which immediately exits the program with no calls to the
normal termination functions (which means that destructors for global and static objects
might not be called).
No cleanups occur for an uncaught exception; that is, no destructors are called. If you don’t
wrap your code (including, if necessary, all the code inmain()) in a try block followed by
handlers and ending with a default handler (catch(…)) to catch all exceptions, then you will
take your lumps. An uncaught exception should be thought of as a programming error.
set_terminate()
You can install your ownterminate() function using the standard
set_terminate() function, which returns a pointer to the terminate()
function you are replacing, so you can restore it later if you want. Your customterminate()
must take no arguments and have avoid return value. In addition, anytermina te() handler
you install must not return or throw an exception, but instead must call some sort of
program- termination function. Ifterminate() is called, it means the problem is unrecoverable.
Likeunexpected(), theterminate() function pointer should never be null.
Here’s an example showing the use ofs et_termina te(). Here, the return value is saved and
restored so thetermina te() function can be used to help isolate the section of code where the
uncaught exception is occurring:

//: C07:Trmnator.cpp

// Use of set_terminate()

// Also shows uncaught exceptions


#include <exception>
#include <iostream>
#include <cstdlib>
using namespace std;
void terminator() {
cout << "I’ll be back!" << endl;
abort();
}

void (*old_terminate)()
= set_terminate(terminator);
class Botch {
public:
class Fruit {};
void f() {
cout << "Botch::f()" << endl;
throw Fruit();
}~Botch() { throw ‘c’; }
};
int main() {
try{
Botch b;
b.f();
} catch(…) {
cout << "inside catch(…)" << endl;
}} ///:~
The definition ofold_termina te looks a bit confusing at first: It not only creates a
pointer to a function, but it initializes that pointer to the return value ofset_terminate(). Even
though you may be familiar with seeing a semicolon right after a pointer-to-function
definition, it’s just another kind of variable and may be initialized when it is defined.
The classBotch not only throws an exception insidef(), but also in
its destructor. This is one of the situations that causes a call to
terminate(), as you can see in main(). Even though the exception handler
sayscatch(…), which would seem to catch everything and leave no cause fortermina te() to
be called,termina te() is called anyway, because in the process of cleaning up the objects on
the stack to handle one exception, theBotch destructor is called, and that generates a
second exception, forcing a call totermina te(). Thus, a destructor that throws an exception or
causes one to be thrown is a design error.
Standard Exceptions
The set of exceptions used with the Standard C++ library are also available for your
own use. Generally it’s easier and faster to start with a standard exception class than to try
to define your own. If the standard class doesn’t do what you need, you can derive from it.

7. Describe the following STL Components:


A) Containers
B) Iterators
C)
Algorithms
Ans –
A)Containers
B)Iterators
Iteration or loops are important statements in c++ which helps to accomplish repeatitive
execution of programming statements. There are three loop statements in C++ : while loop,
do while loop and for loop
While loop
Syntax: while (condition expression)
{Statement1;
Statement 2;
}
In the above example, condition expression is evaluated and if the condition is true, then
the statement1 and statement2 is executed. After execution, the condition is checked again.
If true, the statements inside the while loop are executed again. This continues until the loop
condition becomes false. Hence the variable used in the loop condition should be modified
inside the loop so that the loop termination condition is reached. Otherwise the loop will be
executed infinitely and the program will hang when executed. Also the loop variable should
be iniatialised to avoid the variable taking junk value and create bugs in the program.
C) Algorithms
8. Write about the following with respect to:
A) Instance Diagrams
B) Sequence Diagrams
C) Collaboration Diagrams
Ans –
A)Instance Diagram
Interaction diagrams are composed mainly of instances and messages. Anins ta nce is
said to be the realization of a class that is if we have a classDoctor, than the instances are
Dr. Jones, Dr. Smith, etc. In an object oriented application, instances are what exist when you
instantiate a class (create a new variable with the class as its datatype

In the UML, instances are represented as rectangles with a single label


formatted as:
instanceName: datatype
You can choose to name the instance or not, but the datatype should always be
specified. Below the name, you can also list the attributes and their values. In Visual Case,
you can map attributes from your class and enter new values specific to that instance.
Attributes need only be shown when they are important and you don’t have to specify and
show all of the attributes of a class.
Messages represent operation calls. That is, if an instance calls an
operation in itself or another class, a message is passed. Also, upon the completion of the
operation a return message is sent back to the instance that initiated the call.
The format for message labels is:
Sequence Iteration [Guard] : name (parameters)
Sequence represents the order in which the message is called. The
sequence is redundant on sequence diagrams, but required on
collaboration diagrams
Iteration – an asterix (*) is shown to represent iteration if the message is
called repeatedly.
Guard – an optional boolean expression (the result is either true or false)
that determines if the message is called.
Name represents the operation being called.
Parameters represent the parameters on the operation being called.
B)Sequence Diagram
Sequence diagrams emphasize the order in which things happen, while collaboration
diagrams give more flexibility in their layout. You can use whichever you prefer when
drawing interactions, as both show the same information.
An example sequence diagram for our logon collaboration is shown:
Things to Note:
· The flow of time is shown from top to bottom, that is messages higher
on the diagram happen before those lower down
· The blue boxes areinstances of the represented classes, and the
vertical bars below aretimelines
· The arrows (links) aremessages – operation calls and returns from
operations
· The hide and show messages usegua rds to determine which to call. Guards are always
shown in square braces[ ] and represent constraints on the message (the message is
sent only if the constraint is satisfied)
· The messages are labeled with the operation being called and parameters are shown. You
can choose to enter the parameters or not – this is dependent upon their importance to the
collaboration being shown
· The sequence numbers are not shown on the messages as the
sequence is intrinsic to the diagram
Asynchronous Messages
You can specify a message asasynchronous if processing can continue while the
message is being executed. In the example below, the asynchronous call does not block
processing for the regular call right below. This is useful if the operation being called is run
remotely, or in another thread.
C)Collaboration Diagram
Collaborations are more complex to follow than sequence diagrams, but they do provide the
added benefit of more flexibility in terms of spatial layout.
Above is our logon interaction shown as a collaboration diagram. Notice that each message
is numbered in sequence, because it is not obvious from the diagram, the order of the
messages.
Lollipop Interfaces
Another advantage over the sequence diagram is that collaboration
diagrams allow you to show lollipop interfaces.

Suppose that ourDa ta bas eAccess class implemented an interface called


Queryable. If the logon manager only has access to the interface, we
can show that the message is called through the interface by including a
lollipop interface on the diagram. The stick of the lollipop indicates that
the classDa ta ba s eAcces s realizesQuerya ble.

You might also like