When you execute the program, the compiler displays the output of
the program and comes back to the program editor. To view the output and
wait for user to press any key to return to the editor, type getch() as the last
statement in the program. Getch() is an inbuilt predefined library function
which inputs a character from the user through standard input. However you
should include another header file named conio.h to use this function.
Conio.h contains the necessary declarations for using this function. The
include statement will be similar to iostream.h.
Compiling and Linking
During compilation, if there are any errors that will be listing by the compiler.
The errors may be any one of the following
1. Syntax error
2. Logical error
This error occurs due to the flaw in the logic. This will not be identified
by the compiler. However it can be traced using the debug tool in the editor.
First identify the variable which you suspect creating the error and add them
to watch list by selecting Debug ->Watches->Add watch. Write the variable
name in the watch expression. After adding all the variables required to the
watch list, go to the statement from where you want to observe. If you are
not sure, you can go to the first statement of the program. Then select
Debug ->Toggle Breakpoint (or press ctrl + f8). A red line will appear on the
statement. Then Run the program by selecting Ctrl + f9 or Run option from
run menu. The execution will halt at the statement where you had added the
breakpoint. The watch variables and their values at that point of time will be
displayed in the bottom in the watch window. Press F8 to execute the next
statement till you reach the end of the program. In this way you can watch
closely the values in the watch variables after execution of each and every
statement in the program. If you want to exit before execution of the last
statement press Ctrl + Break. To remove the breakpoint in the program go
to the statement where you have added breakpoint select Debug ->Toggle
Breakpoint (or press ctrl + f8). Select Debug -> watch ->remove watches to
remove the variables in the watch list. This tool helps in knowing the values
taken by the variable at each and every step. You can compare the expected
value with the actual value to identify the error.
3. Linker error
This error occur when the files during linking are missing or mispelt
4. Runtime error
This error occurs if the programs encounters division by zero, accessing a
null pointer etc during execution of the program
2. Describe the theory with programming examples the selection control statements in
C++.
Ans.
If statement
// evenodd.cpp
# include <iostream.h>
# include <conio.h>
void main()
{
int num;
cout<<”Please enter a number”<<endl;
cin>>num;
if ((num%2) == 0)
cout<<num <<” is a even number”;
else
cout<<num <<” is a odd number”;
getch();
}
The above program accepts a number from the user and divides it by 2
and if the remainder (remainder is obtained by modulus operator) is zero, it
displays the number is even, otherwise as odd. We make use of the
relational operator == to compare whether remainder is equal to zero or not.
Nested If statement
If (condition1)
{ if (condition 2)
{ statement1;
Statement2;
}
else if (condition3)
{statement3;
}
}
else statement4;
In the above example statement1 will be executed if both the condition1 and
condition2 are true and in all other cases statement2 will be executed.
If ((condition1 || (condition2))
statement1;
else
statement2;
//Large.cpp
# include <iostream.h>
void main()
{ int a,b,c;
cout<<”Please enter three numbers”;
cin>>a>>b>>c;
if ((a>b) && (b>c))
cout<<a<< “ is the largest number”;
else if ((b>a) && (b>c))
cout<<b<< “ is the largest number”;
else if ((c>a) && (c>b))
cout<<c<< “ is the largest number”;
}
The above program accepts three numbers from the user and displays
which is the largest number among the three.( assumption is that all the
numbers are unique, the program has to be modified if you would like to
allow same number twice)
B) switch statements
Switch statement
Syntax :
Switch (variablename)
{ case value1: statement1;
break;
case value2: statement2;
break;
case value3: statement3;
break;
default: statement4;
}
position.cpp
# include<iostream.h>
void main()
{ char pos;
int x=15, y=15;
cout << “ you are currently located at” <<x<<” “<<y<<endl;
cout>>”please choose the letter to move l for left, r for right, u for up and d
for down” <<endl;
cin>>pos;
switch (pos)
{ case ‘l’: x–;
break;
case ‘r’: x++;
break;
case ‘u’: y++;
break;
case ‘d’: y–;
break;
default: cout<<”You selected a wrong option”;
}
cout<<“ you are now located at” <<x<<” “<<y;
}
The above program asks the user to enter l,r,u,d for allowing him to
move left,right,up and down respectively. The position is initialised to 15 and
15 which are x and y coordinates of his position. Depending upon the what
user has selected the the x and y co-ordinates are incremented or
decremented by one(x++ is same as x=x+1). If the user types a letter other
than l,r,u,d, he gets an error message. Since the switch variable is a
character, l,u,r,d and enclosed within single quote.
Ans.
#include<iostream.h>
#include<conio.h>
void main()
{
clrscr();
int a[3][3],i,j,k,sp,minr,pos,flag=1;
cout<<"Enter the contents of the array ";
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
cin>>a[i][j];
}
cout<<"
The matrix representation of array is: ";
for(i=0;i<3;i++)
{
cout<<"
";
for(j=0;j<3;j++)
cout<<a[i][j]<<" ";
}
cout<<endl;
for(i=0;i<3;i++)
{
flag=1;
sp=a[i][0],pos=0;
for(j=1;j<3;j++)
{
if(a[i][j]<sp)
{ sp=a[i][j];
pos=j;
}
}
for(k=0;k<3;k++)
{
if(a[k][pos]<sp)
{
flag=0;
break;
}
}
if(flag==1)
cout<<"The saddle point of row "<<i+1<<" is "<<sp<<endl;
}
getch();
}
Pass by Value
Consider a pair of C++ functions defined in Program. The function One calls
the function Two. In general, every function call includes a (possibly empty)
list of arguments. The arguments specified in a function call are called actual
parameters . In this case, there is only one actual parameter y.
void Two(int x)
{
x=2;
cout << r << endl;
}
void One()
{
int y=1;
Two(y);
cout << y << endl;
}
Program: Example of Pass-By-Value Parameter Passing
The method by which the parameter is passed to a function is determined by
the function definition. In this case, the function Two is defined as accepting
a single argument of type int called x. The arguments which appear in a
function definition are called formal parameters . If the type of a formal
parameter is not a reference , then the parameter passing method is pass-
by-value.
The semantics of pass-by-value work like this: The effect of the formal
parameter definition is to create a local variable of the specified type in the
given function. E.g., the function Two has a local variable of type int called x.
When the function is called, the values (r-values) of the actual parameters
are used to initialize the formal parameters before the body of the function is
executed.
Since the formal parameters give rise to local variables, if a new value is
assigned to a formal parameter, that value has no effect on the actual
parameters. Therefore, the output obtained produced by the function One
defined in Program is:
Pass by Reference
Consider the pair of C++ functions defined in Program . The only difference
between this code and the code given in Program is the definition of the
formal parameter of the function Two: In this case, the parameter x is
declared to be a reference to an int. In general, if the type of a formal
parameter is a reference, then the parameter passing method is pass-by-
reference .
void Two(int& x)
{
x=2;
cout << r << endl;
}
void One()
{
int y=1;
Two(y);
cout << y << endl;
}
Program: Example of Pass-By-Reference Parameter Passing
A reference formal parameter is not a variable. When a function is called that
has a reference formal parameter, the effect of the call is to associate the
reference with the corresponding actual parameter. I.e., the reference
becomes an alternative name for the corresponding actual parameter.
Consequently, this means that the actual parameter passed by reference
must be variable.
A reference formal parameter can be used in the called function everywhere
that a variable can be used. In particular, if the reference formal parameter
is used where a r-value is required, it is the r-value of actual parameter that
is obtained. Similarly, if the reference parameter is used where an l-value is
required, it is the l-value of actual parameter that is obtained. Therefore, the
output obtained produced by the function one defined in Program is:
2
2
Derivation
In the declaration of a derived class, you list the base classes of the derived
class. The derived class inherits its members from these base classes.
The following example shows the declaration of the derived class D and the
base classes V, B1, and B2. The class B1 is both a base class and a derived
class because it is derived from class V and is a base class for D:
class V { /* ... */ };
class B1 : virtual public V { /* ... */ };
class B2 { /* ... */ };
Classes that are declared but not defined are not allowed in base lists.
For example:
class X;
// error
class Y: public X { };
The compiler will not allow the declaration of class Y because X has not been
defined.
When you derive a class, the derived class inherits class members of the
base class. You can refer to inherited members (base class members) as if
they were members of the derived class. For example:
class Base {
public:
int a,b;
};
class Derived : public Base {
public:
int c;
};
int main() {
Derived d;
d.a = 1; // Base::a
d.b = 2; // Base::b
d.c = 3; // Derived::c
}
The derived class can also add new class members and redefine existing
base class members. In the above example, the two inherited members, a
and b, of the derived class d, in addition to the derived class member c, are
assigned values. If you redefine base class members in the derived class,
you can still refer to the base class members by using the :: (scope
resolution) operator. For example:
#include <iostream>
using namespace std;
class Base {
public:
char* name;
void display() {
cout << name << endl;
}
};
int main() {
Derived d;
d.name = "Derived Class";
d.Base::name = "Base Class";
// call Derived::display()
d.display();
// call Base::display()
d.Base::display();
}
You can manipulate a derived class object as if it were a base class object.
You can use a pointer or a reference to a derived class object in place of a
pointer or reference to its base class. For example, you can pass a pointer or
reference to a derived class object D to a function expecting a pointer or
reference to the base class of D. You do not need to use an explicit cast to
achieve this; a standard conversion is performed. You can implicitly convert
a pointer to a derived class to point to an accessible unambiguous base
class. You can also implicitly convert a reference to a derived class to a
reference to a base class.
#include <iostream>
using namespace std;
class Base {
public:
char* name;
void display() {
cout << name << endl;
}
};
int main() {
Derived d;
d.name = "Derived Class";
d.Base::name = "Base Class";
// call Base::display()
bptr->display();
The reverse case is not allowed. You cannot implicitly convert a pointer or a
reference to a base class object to a pointer or reference to a derived class.
For example, the compiler will not allow the following code if the classes
Base and Class are defined as in the above example:
int main() {
Base b;
b.name = "Base class";
The compiler will not allow the statement Derived* dptr = &b because the
statement is trying to implicitly convert a pointer of type Base to a pointer of
type Derived.
If a member of a derived class and a member of a base class have the same
name, the base class member is hidden in the derived class. If a member of
a derived class has the same name as a base class, the base class name is
hidden in the derived class.
Inheritance
Inheritance is almost like embedding an object into a class. Suppose that you
declare an object x of class A in the class definition of B. As a result, class B
will have access to all the public data members and member functions of
class A. However, in class B, you have to access the data members and
member functions of class A through object x. The following example
demonstrates this:
#include <iostream>
using namespace std;
class A {
int data;
public:
void f(int arg) { data = arg; }
int g() { return data; }
};
class B {
public:
A x;
};
int main() {
B obj;
obj.x.f(20);
cout << obj.x.g() << endl;
// cout << obj.g() << endl;
}
In the main function, object obj accesses function A::f() through its data
member B::x with the statement obj.x.f(20). Object obj accesses A::g() in a
similar manner with the statement obj.x.g(). The compiler would not allow
the statement obj.g() because g() is a member function of class A, not class
B.
The inheritance mechanism lets you use a statement like obj.g() in the above
example. In order for that statement to be legal, g() must be a member
function of class B.
Inheritance lets you include the names and definitions of another class's
members as part of a new class. The class whose members you want to
include in your new class is called a base class. Your new class is derived
from the base class. The new class contains a sub object of the type of the
base class. The following example is the same as the previous example
except it uses the inheritance mechanism to give class B access to the
members of class A:
#include <iostream>
using namespace std;
class A {
int data;
public:
void f(int arg) { data = arg; }
int g() { return data; }
};
class B : public A { };
int main() {
B obj;
obj.f(20);
cout << obj.g() << endl;
}
Class A is a base class of class B. The names and definitions of the members
of class A are included in the definition of class B; class B inherits the
members of class A. Class B is derived from class A. Class B contains a
subobject of type A.
You can also add new data members and member functions to the derived
class. You can modify the implementation of existing member functions or
data by overriding base class member functions or data in the newly derived
class.
You may derive classes from other derived classes, thereby creating another
level of inheritance. The following example demonstrates this:
struct A { };
struct B : A { };
struct C : B { };
A direct base class is a base class that appears directly as a base specifier in
the declaration of its derived class.
An indirect base class is a base class that does not appear directly in the
declaration of the derived class but is available to the derived class through
one of its base classes. For a given class, all base classes that are not direct
base classes are indirect base classes. The following example demonstrates
direct and indirect base classes:
class A {
public:
int x;
};
class B : public A {
public:
int y;
};
class C : public B { };
Friend function
The friend function is written as any other normal function, except the
function declaration of these functions is preceded with the keyword friend.
The friend function must have the class to which it is declared as friend
passed to it in argument.
The keyword friend is placed only in the function declaration of the friend
function and not in the function definition.
A friend function, even though it is not a member function, would have the
rights to access the private members of the class.
The function can be invoked without the use of an object. The friend function
has its argument as objects, seen in example below.
#include
class exforsys
{
private:
int a,b;
public:
void test()
{
a=100;
b=200;
}
friend int compute(exforsys e1)
//Friend Function Declaration with keyword friend and with the object of class
exforsys to which it is friend passed to it
};
main()
{
exforsys e;
e.test();
cout<<"The result is:"< //Calling of Friend Function with object as argument.
}
Friend Class
C++ provides the friend keyword to do just this. Inside a class, you can
indicate that other classes (or simply functions) will have direct access to
protected and private members of the class. When granting access to a
class, you must specify that the access is granted for a class using the class
keyword:
friend class aClass;
Note that friend declarations can go in either the public, private, or protected
section of a class--it doesn't matter where they appear. In particular,
specifying a friend in the section marked protected doesn't prevent the
friend from also accessing private fields. Here is a more concrete example of
declaring a friend:
class Node
{
private:
int data;
int key;
// ...
friend class BinaryTree; // class BinaryTree can now access data directly
};
Now, Node does not need to provide any means of accessing the data stored
in the tree. The BinaryTree class that will use the data is the only class that
will ever need access to the data or key. (The BinaryTree class needs to use
the key to order the tree, and it will be the gateway through which other
classes can access data stored in any particular node.) Now in the
BinaryTree class, you can treat the key and data fields as though they were
public:
class BinaryTree
{
private:
Node *root;
Ans.
So far we have seen just one way to open a file, either for reading,
either for writing. But it can be opened another way too. So far, you should
be aware of this method:
ifstream OpenFile(“cpp-home.txt”);
Well, this is not the only way. As mentioned before, the above code
creates an object from class ifstream, and passes the name of the file to be
opened to its constructor. But in fact, there are several overloaded
constructors, which can take more than one parameter. Also, there is
function open() that can do the same job. Here is an example of the above
code, but using the open() function:
ifstream OpenFile;
OpenFile.open(“cpp-home.txt”);
Other use of open() is for example if you open a file, then close it, and
using the same file handle open another file. This way, you will need the
open() function.
#include <fstream.h>
void read(ifstream &T) { //pass the file stream to the function
//the method to read a file
char ch;
while(!T.eof()) {
T.get(ch);
cout << ch;
}
cout << endl << "——–" << endl;
}
void main() {
ifstream T("file1.txt");
read(T);
T.close();
T.open("file2.txt");
read(T);
T.close();
}
So, as long as file1.txt and file2.txt exists and has some text into, you will
see it.
You should know that filename is the name of the file (a string). What
is new here is the open_mode. The value of open_mode defines how to a file
can be opened. Here is a table of the open modes:
All these values are int constants from an enumerated type. But for
making your life easier, you can use them as you see them in the table. Here
is an example on how to use the open modes:
#include <fstream.h>
void main() {
ofstream SaveFile("file1.txt", ios::ate);
SaveFile << "That’s new!n";
SaveFile.close();
}
As you see in the table, using ios::ate will write at the end of the file. If
it wasn’t used, the file would have been overwritten. So, if file1.txt has this
text:
Running the above code, will add “That’s new!” to it, so it will look this way:
If you want to set more than one open mode, just use the OR operator (|).
This way:
ios::ate | ios::binary
Using different open modes helps make file handling an easy job. Having
In fact, that is only the declaration. The code line above creates a file
stream handle, named File. As you know, this is an object from class fstream.
When using fstream, you should specify ios::in and ios::out as open modes.
This way, you can read from the file, and write in it, in the same time,
without creating new file handles. Well, of course, you can only read or write.
Here is the code example:
#include <fstream.h>
void main() {
fstream File("test.txt", ios::in | ios::out);
File << "Hi!"; //put “Hi!” in the file
static char str[10]; //when using static, the array is automatically
//initialized, and very cell NULLed
File.seekg(ios::beg); //get back to the beginning of the file
//this function is explained a bit later
File >> str;
cout << str << endl;
File.close();
}
This line, creates an object from class fstream. At the time of execution, the
program opens the file test.txt in read/write mode. This means, that you can
read from the file, and put data into it, at the same time.
I am sure the reader is aware of this and hence the explanation for this
statement is redundant.
This makes a char array with 10 cells. The word static initializes the array
when at the time of creation.
File.seekg(ios::beg);
while(!OpenFile.eof()) {
OpenFile.get(ch);
cout << ch;
}
This is a while loop, that will loop until you reach the end of the file.
But how does the loop know if the end of the file is reached? The answer is;
when you read the file, there is something like an inside-pointer (current
reading/writing position) that shows where you are up to, with the reading
(and writing, too). Every time you call OpenFile.get(ch) it returns the current
character to the ch variable, and moves the inside-pointer one character
after that, so that the next time this function is called, it will return the next
character. And this repeats, until you reach the end of the file.
Going back to the code line; the function seekg() will put the inside-pointer to
a specific place (specified by you). One can use:
Or you can also set the number of characters to go back or after. For
example, if you want to go 5 characters back, you should write:
File.seekg(-5);
File.seekg(40);
It is imperative to mention that the seekg() function is overloaded, and it can
take two parameters, too. The other version is this one:
File.seekg(-5, ios::end);
In this example, you will be able to read the last 4 characters of the text,
because:
Why you will read 4 but not 5 characters? One character is lost, because the
last thing in the file is neither a character nor white space. It is just position
(i.e., end of file).
Why this function was used the program above. After putting “Hi!” in the file,
the inside-pointer was set after it, i.e., at the end of the file. And as we want
to read the file, there is nothing that can be read at the end. Hence, we have
to put the inside-pointer at the beginning. And that is exactly what this
function does.
I believe this line reminds us of cin >>. In fact, it has much to do with it. This
line reads one word from the file, and puts it into the specified array. For
example, if the file has this text:
Using File >> str, will put just “Hi!” to the str array. And, as what we put in
the file was “Hi!” we don’t need to do a while loop, that takes more time to
code. That’s why this technique was used. By the way, in the while loop for
reading, that was used so far, the program reads the file, char by char. But
you can read it word by word, this way:
char str[30]; //the word can’t be more than 30 characters long
while(!OpenFile.eof()){
OpenFile >> str;
cout << str;
}
You can also read it line by line, this way:
char line[100]; //a whole line will be stored here
while(!OpenFile.eof()) {
OpenFile.getline(line,100); //where 100 is the size of the array
cout << line << endl;
}
8. Explain the concept of class templates in C++ with some real time
programming examples.
Ans.
A class template definition looks like a regular class definition, except it is
prefixed by the keyword template. For example, here is the definition of a
class template for a Stack.
template <class T>
class Stack {
public:
Stack(int = 10);
~Stack() { delete [] stackPtr ; }
int push(const T&);
int pop(T&);
int isEmpty()const { return top == -1; }
int isFull() const { return top == size – 1; }
private:
int size; // number of elements on Stack.
int top;
T* stackPtr;
};
When compiling B.cpp, the compiler has both the declarations and the
definitions available. At this point the compiler does not need to generate
any definitions for template classes, since there are no instantiations. When
the compiler compiles main.cpp, there are two instantiations: template class
B<int> and B<float>. At this point the compiler has the declarations but no
definitions.
//stack.h
#pragma once
template <class T>
class Stack {
public:
Stack(int = 10);
~Stack() { delete [] stackPtr; }
int push(const T&);
int pop(T&); // pop an element off the stack
int isEmpty()const { return top == -1; }
int isFull() const { return top == size – 1; }
private:
int size; // Number of elements on Stack
int top;
T* stackPtr;
};
//constructor with the default size 10
template <class T>
Stack<T>::Stack(int s) {
size = s > 0 && s < 1000 ? s : 10;
top = -1; // initialize stack
stackPtr = new T[size];
}
// push an element onto the Stack
template <class T>
int Stack<T>::push(const T& item) {
if (!isFull())
{
stackPtr[++top] = item;
return 1; // push successful
}
return 0; // push unsuccessful
}
// pop an element off the Stack
template <class T>
int Stack<T>::pop(T& popValue) {
if (!isEmpty())
{
popValue = stackPtr[top--];
return 1; // pop successful
}
return 0; // pop unsuccessful
}
#include <iostream>
#include "stack.h"
using namespace std;
void main() {
typedef Stack<float> FloatStack;
typedef Stack<int> IntStack;
FloatStack fs(5);
float f = 1.1;
cout << "Pushing elements onto fs" << endl;
while (fs.push(f))
{
cout << f << ‘ ‘;
f += 1.1;
}
cout << endl << "Stack Full." << endl
<< endl << "Popping elements from fs" << endl;
while (fs.pop(f))
cout << f << ‘ ‘;
cout << endl << "Stack Empty" << endl;
cout << endl;
IntStack is;
int i = 1.1;
cout << "Pushing elements onto is" << endl;
while (is.push(i))
{
cout << i << ‘ ‘;
i += 1;
}
cout << endl << "Stack Full" << endl
<< endl << "Popping elements from is" << endl;
while (is.pop(i))
cout << i << ‘ ‘;
cout << endl << "Stack Empty" << endl;
}
Output:
Stack Empty
· typedef’s are very useful when "templates of templates" come into usage.
For example, when instantiating an STL vector of int’s, you could use:
· If the template definition changes, simply change the typedef definition. For
example, currently the definition of template class vector requires a second
parameter.
Ans.
Constructor
Constructor is a special member function that takes the same name as the
class name. The syntax generally is as given below:
X::X()
There are several forms in which a constructor can take its shape namely:
Default Constructor:
For example:
class Exforsys
{
private:
int a,b;
public:
Exforsys();
...
};
Exforsys :: Exforsys()
{
a=0;
b=0;
}
Copy constructor:
This constructor takes one argument. Also called one argument constructor.
The main use of copy constructor is to initialize the objects while in creation,
also used to copy an object. The copy constructor allows the programmer to
create a new object from an existing one by initialization.
Exforsys e3(e2);
or
Exforsys e3=e2;
For Example:
#include <iostream.h>
class Exforsys()
{
private:
int a;
public:
Exforsys()
{}
Exforsys(int w)
{
a=w;
}
Exforsys(Exforsys& e)
{
a=e.a;
cout<<” Example of Copy Constructor”;
}
void result()
{
cout<< a;
}
};
void main()
{
Exforsys e1(50);
Exforsys e3(e1);
cout<< “\ne3=”;e3.result();
}
In the above the copy constructor takes one argument an object of type
Exforsys which is passed by reference. The output of the above program is
The programmer cannot declare a constructor as virtual or static, nor can the
programmer declare a constructor as const, volatile, or const volatile.
Destructors
Syntax
~ classname();
The above is the general syntax of a destructor. In the above, the symbol
tilda ~ represents a destructor which precedes the name of the class.
Like the constructor, the destructor must also be defined in the public. The
destructor must be a public member.
The Destructor does not take any argument which means that destructors
cannot be overloaded.
class Exforsys
{
private:
……………
public:
Exforsys()
{}
~ Exforsys()
{}
}
A. Types of Inheritance
Single Inheritance
In "single inheritance," a common form of inheritance, classes have only one
base class.
class CFather
{
public:
void Gender () {cout<<"Male" ;}
void Blood () {cout<<"Red";}
void Initial (){cout<<"Angajala";}
void Address (){cout <<"******" ;}
};
Class CDerived:public CBase
{
};
Multilevel Inheritance
It is the enhancement of the concept of inheritance. When a subclass is
derived from a derived class then this mechanism is known as the multilevel
inheritance. The derived class is called the subclass or child class for its
parent class and this parent class works as the child class for it's just above
(parent) class. Multilevel inheritance can go up to any number of levels.
The best example is Say we have 3 classes
ClassA, ClassB and ClassC. ClassB is derived from ClassA and ClassC is
derived ClassB
This is multi level inheritance..
ClassA
^
|
ClassB
^
|
ClassC
. class CFather
{
public:
void Gender () {cout<<"Male" ;}
void Blood () {cout<<"Red";}
void Initial (){cout<<"Angajala";}
void Address (){cout <<"******" ;}
};
Class CDerived:public CBase
{
};
Class C2Derived:public CDerived
{
};
Multiple Inheritances
You can derive a class from any number of base classes. Deriving a class
from more than one direct base class is called multiple inheritances.
In the following example, classes A, B, and C are direct base classes for the
derived class X:
class A { /* ... */ };
class B { /* ... */ };
class C { /* ... */ };
class X : public A, private B, public C { /* ... */ };
Hierarchical Inheritance
It is a type of inheritance where one or more derived classes is derived from
common( or one ) base class
E.g.
class A
{
// definition of class A
};
class B : public A //derived from A
{
// definition of class B
};
class C : public A //derived from A
{
// definition of class c
};
Hybrid Inheritance
In this type of inheritance, we can have mixture of number of inheritances
but this can generate an error of using same name function from no of
classes, which will bother the compiler to how to use the functions.
Therefore, it will generate errors in the program. This has known as
ambiguity or duplicity.
Let's say that we are writing a text-based medieval video game. Our video
game will have two types of characters: the players and the monsters. A
player has to know the values of certain attributes: health, strength, and
agility. A player must also know what type of weapon and what type of armor
they possess. A player must be able to move through a maze, attack a
monster, and pick up treasure. So, to design this "player object", we must
first separate data that the player object must know from actions that the
player must know how to execute. The definition for a player object could be:
Player Object:
data:
health
strength
agility
type of weapon
type of armor
actions:
move
attack monster
get treasure
END;
Data that an object keeps track of is called member data and actions that an
object knows how to do are called member functions. Member data is very
similar to variables in a regular function in the sense that no other object can
get access to that data (unless given permission by the object). Member data
keeps its values over the life of an object
There is a very important distinction between an object and an instance of
an object. An object is actually a definition, or a template for instances of
that object. An instance of an object is an actual thing that can be
manipulated. For instance, we could define a Person object, which may
include such member data as hair color, eye color, height, weight, etc. An
instance of this object could be "Dave" and Dave has values for hair color,
eye color, etc. This allows for multiple instances of an object to be created.
Let's go back to the medieval video game example and define the monster
object.
Our Player object has three pieces of data that it owns: strength, agility, and
health. These are a part of the player object. That makes sense in real world
terms. The player knows about two other pieces of data: the weapon and the
armor that the player possesses. Here's a diagram for an instance of the
player object.
So that is how to conceptually think of pointers. Now what's really going on?
Memory in a computer is a complicated thing, but let's reduce it to it's
simplest form: one large string of slots with addresses that data can be put
in. As in the following picture:
If we were to access the spot in memory with address 3, we would get the
value 45. If we were to access the spot in memory with address 2 we would
get the value "Dave". The previous diagram over simplifies two important
concepts, however
3. Describe the theory behind Virtual Functions and Polymorphism along with suitable
programming examples for each.
Virtual, as the name implies, is something that exists in effect but not in
reality. The concept of virtual function is the same as a function, but it does
not really exist although it appears in needed places in a program. The
object-oriented programming language C++ implements the concept of
virtual function as a simple member function, like all member functions of
the class.
Virtual functions are member functions declared with the keyword virtual.
class classname //This denotes the base class of C++ virtual function
{
public:
virtual void memberfunctionname() //This denotes the C++ virtual function
{
.............
............
}
};
Eg.
class BaseClass{
public:
virtual void who(void)
{
cout << "Base\n";
}
};
class Derived1 : public BaseClass
{
public:
void who (void)
{
cout << "Derived Class 1 \n";
}
};
bp = &b;
bp ->who();//Executes the base class who function
bp = &d1;
bp ->who();//Executes the Derived1 class who function
bp = &d2;
bp ->who();//Executes the Derived2 class who function
}
//Out put
//Base
//Derived Class 1
//Derived Class 2
6 + 10
The same + operator can be used with different meanings with strings:
"Exforsys" + "Training"
The same + operator can also be used for floating point addition:
7.15 + 3.78
Polymorphism is a powerful feature of the object oriented programming
language C++. A single operator + behaves differently in different contexts
such as integer, float or strings referring the concept of polymorphism. The
above concept leads to operator overloading. The concept of overloading is
also a branch of polymorphism. When the exiting operator or function
operates on new data type it is overloaded. This feature of polymorphism
leads to the concept of virtual methods.
All different classes must be derived from a single base class. In the above
example, the shapes of vehicles (circle, triangle, rectangle) are from the
single base class called Shape.
The member function must be declared virtual in the base class. In the
above example, the member function for making the vehicle should be made
as virtual to the base class.
Types of Polymorphism:
C++ provides three different types of polymorphism.
•Virtual functions
•Function name overloading
•Operator overloading
In addition to the above three types of polymorphism, there exist other kinds
of polymorphism:
•run-time
•compile-time
•ad-hoc polymorphism
•parametric polymorphism
4. Write a program in C++ for copying and printing the contents of files.
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);
}
Ans.
Many C++ programs use common data structures like stacks, queues and
lists. A program may require a queue of customers and a queue of
messages. One could easily implement a queue of customers, then take the
existing code and implement a queue of messages. The program grows, and
now there is a need for a queue of orders. So just take the queue of
messages and convert that to a queue of orders (Copy, paste, find,
replace????). Need to make some changes to the queue implementation?
Not a very easy task, since the code has been duplicated in many places. Re-
inventing source code is not an intelligent approach in an object oriented
environment which encourages re-usability. It seems to make more sense to
implement a queue that can contain any arbitrary type rather than
duplicating code. How does one do that? The answer is to use type
parameterization, more commonly referred to as templates.
Class Templates
//B.H
template <class t>
class b
{
public:
b() ;
~b() ;
};
// B.CPP
#include "B.H"
template <class t>
b<t>::b()
{
}
template <class t>
b<t>::~b()
{
}
//MAIN.CPP
#include "B.H"
void main()
{
b<int> bi ;
b <float> bf ;
}
When compiling B.cpp, the compiler has both the declarations and the
definitions available. At this point the compiler does not need to generate
any definitions for template classes, since there are no instantiations. When
the compiler compiles main.cpp, there are two instantiations: template class
B<int> and B<float>. At this point the compiler has the declarations but no
definitions!
//stack.h
#pragma once
template <class T>
class Stack
{
public:
Stack(int = 10) ;
~Stack() { delete [] stackPtr ; }
int push(const T&);
int pop(T&) ; // pop an element off the stack
int isEmpty()const { return top == -1 ; }
int isFull() const { return top == size - 1 ; }
private:
int size ; // Number of elements on Stack
int top ;
T* stackPtr ;
};
Using a class template is easy. Create the required classes by plugging in the
actual type for the type parameters. This process is commonly known as
"Instantiating a class". Here is a sample driver class that uses the Stack class
template.
#include <iostream>
#include "stack.h"
using namespace std ;
void main()
{
typedef Stack<float> FloatStack ;
typedef Stack<int> IntStack ;
FloatStack fs(5) ;
float f = 1.1 ;
cout << "Pushing elements onto fs" << endl ;
while (fs.push(f))
{
cout << f << ' ' ;
f += 1.1 ;
}
cout << endl << "Stack Full." << endl
<< endl << "Popping elements from fs" << endl ;
while (fs.pop(f))
cout << f << ' ' ;
cout << endl << "Stack Empty" << endl ;
cout << endl ;
IntStack is ;
int i = 1.1 ;
cout << "Pushing elements onto is" << endl ;
while (is.push(i))
{
cout << i << ' ' ;
i += 1 ;
}
cout << endl << "Stack Full" << endl
<< endl << "Popping elements from is" << endl ;
while (is.pop(i))
cout << i << ' ' ;
cout << endl << "Stack Empty" << endl ;
}
Function Templates
Function templates are implemented like regular functions, except they are
prefixed with the keyword template. Here is a sample with a function
template.
#include <iostream>
using namespace std ;
//max returns the maximum of the two elements
template <class T>
T max(T a, T b)
{
return a > b ? a : b ;
}
Using function templates is very easy: just use them like regular functions.
When the compiler sees an instantiation of the function template, for
example: the call max(10, 15) in function main, the compiler generates a
function max(int, int). Similarly the compiler generates definitions for
max(char, char) and max(float, float) in this case.
#include <iostream>
using namespace std ;
//max returns the maximum of the two elements
template <class T>
T max(T a, T b)
{
return a > b ? a : b ;
}
void main()
{
cout << "max(10, 15) = " << max(10, 15) << endl ;
cout << "max('k', 's') = " << max('k', 's') << endl ;
cout << "max(10.1, 15.2) = " << max(10.1, 15.2) << endl ;
}
6. Discuss the theory of Exception specifications with suitable code snippets for each.
Ans.
C++ provides a mechanism to ensure that a given function is limited to
throwing only a specified list of exceptions. An exception specification at the
beginning of any function acts as a guarantee to the function's caller that the
function will throw only the exceptions contained in the exception
specification.
>>-throw--(--+--------------+--)-------------------------------><
'-type_id_list-'
class A { };
class B : public A { };
class C { };
class A {
public:
virtual void f() throw (int, char);
};
class B : public A{
public: void f() throw (int) { }
};
class D : public A {
public: void f() throw (int, char, double) { }
};
*/The compiler allows B::f() because the member function may throw only
exceptions of type int. The compiler would not allow C::f() because the
member function may throw any kind of exception. The compiler would not
allow D::f() because the member function can throw more types of
exceptions (int, char, and double) than A::f().
void (*f)();
void (*g)();
void (*h)() throw (int);
void i() {
f = h;
// h = g; This is an error.
}The compiler allows the assignment f = h because f can throw any kind of
exception. The compiler would not allow the assignment h = g because h can
only throw objects of type int, while g can throw any kind of exception.
class A {
public:
A() throw (int);
A(const A&) throw (float);
~A() throw();
};
class B {
public:
B() throw (char);
B(const A&);
~B() throw();
};
Ans:
The term "sequence analysis" in biology implies subjecting a DNA or peptide sequence to
sequence alignment, sequence databases, repeated sequence searches, or other bioinformatics
methods on a computer.
Since the development of methods of high-throughput production of gene and protein sequences
during the 90s, the rate of addition of new sequences to the databases increases continuously.
Such a collection of sequences does not, by itself, increase the scientist's understanding of the
biology of organisms. However, comparing sequences with known functions with these new
sequences is one way of understanding the biology of that organism from which the new
sequence comes. Thus, sequence analysis can be used to assign function to genes and proteins by
the study of the similarities between the compared sequences. Nowadays there are many tools
and techniques that provide the sequence comparisons (sequence alignment) and analyze the
alignment product to understand the biology.
A. Instance Diagrams
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.
Sequence represents the order in which the message is called. The sequence
is redundant on sequence diagrams, but required on collaboration diagrams
Guard – an optional boolean expression (the result is either true or false) that
determines if the message is called.
B) Sequence Diagrams
· 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 are instances of the represented classes, and the vertical
bars below are timelines
· The arrows (links) are messages – operation calls and returns from
operations
· The hide and show messages use guards 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
C) Collaboration Diagrams
Collaborations are more complex to follow than sequence diagrams, but they
do provide the added benefit of more flexibility in terms of spatial layout.
Lollipop Interfaces