Upload
phungtuyen
View
223
Download
0
Embed Size (px)
Citation preview
DHANALAKSHMI COLLEGE OF ENGINEERING,
CHENNAI
Department of Computer Science and Engineering
CS6301 PROGRAMMING AND DATA STRUCTURES-II
Anna University 2 & 16 Mark Questions & Answers
Year / Semester: II / III
Regulation: 2013
Academic year: 2017 - 2018
PART A
1. How does a C string differs from a C++ type string? [M/J – 16] [N/D-15]
In C, strings are just char arrays which, by convention, end with a NUL byte. In terms of
dynamic memory management, you can simply malloc the space for them (including the extra
byte). Memory management when modifying strings is your responsibility:
char *s = strdup ("Hello");
char *s2 = malloc (strlen (s) + 6);
strcpy (s2, s);
strcat (s2, ", Pax");
free (s);
s = s2;
In C++, strings (std::string) are objects with all the associated automated memory management
and control which makes them a lot safer and easier to use, especially for the novice. For
dynamic allocation, use something like:
std::string s = "Hello";
s += ", Pax";
2. Distinguish the term overloading and overriding. [M/J – 16]
Overloading occurs when two or more methods in one class have the same method name but
different parameters. Overriding means having two methods with the same method name and
parameters (i.e., method signature). One of the methods is in the parent class and the other is in
the child class.
3. Give the list of operators that cannot be overloaded.
?: (conditional)
. ( member selection)
.* (member selection with pointer-to-member)
:: (scope resolution)
sizeof (object size information)
typeid (object type information)
4. Differentiate compile and runtime polymorphism.
Compile time Polymorphism, call is resolved by
the compiler.
In Run time Polymorphism, call is not resolved by
the compiler.
It is also known as Static binding, Early
bindingand overloading as well.
It is also known as Dynamic binding, Late
bindingand overriding as well.
Overloading is compile time polymorphism where Overriding is run time polymorphism having
more than one methods share the same name with
different parameters or signature and different
return type.
same method with same parameters or signature,
but associated in a class & its subclass.
It is achieved by function overloading
andoperator overloading.
It is achieved by virtual functions and pointers.
It provides fast execution because known early at
compile time.
It provides slow execution as compare to early
binding because it is known at runtime.
Compile time polymorphism is less flexible as all
things execute at compile time.
Run time polymorphism is more flexible as all
things execute at run time.
5. Define copy constructor and its use.
The copy constructor is a constructor which creates an object by initializing it with an object
of the same class, which has been created previously. The copy constructor is used to: Initialize
one object from another of the same type. Copy an object to pass it as an argument to a function.
6. What are the special properties of virtual functions?
Dynamic binding: virtual functions are resolved during run time or dynamic binding.
Virtual functions are member functions of a class.
Virtual functions are declared with the keyword virtual.
Virtual function takes a different functionality in the derived class.
8. What is dynamic initialization of objects?
Dynamic initialization of object refers to initializing the objects at run time i.e. the initial value
of an object is to be provided during run time. Dynamic initialization can be achieved using
constructors and passing parameters values to the constructors. This type of initialization is
required to initialize the class variables during run time.
10. What are pure virtual functions? Give example.
A pure virtual function or pure virtual method is a virtual function that is required to be
implemented by a derived class if the derived class is not abstract. Classes containing pure
virtual methods are termed "abstract" and they cannot be instantiated directly.
class Animal {
public:
void /*non-virtual*/ move(void) {
std::cout << "This animal moves in some way" << std::endl;
}
virtual void eat(void) = 0;
};
// The class "Animal" may possess a definition for eat() if desired.
class Llama : public Animal {
public:
// The non virtual function move() is inherited but not overridden
void eat(void) override {
std::cout << "Llamas eat grass!" << std::endl;
}
};
Part B
12. (a) (i) Write a C++ program to overload the decrement operator with prefix and postfix
forms.
#include<iostream>
using namespace std;
class pp
{
int a,b;
public:
pp()
{
a=5;
b=-5;
}
void show()
{
cout<<" a="<<a<<" and b="<<b;
}
void operator --()
{
--a;
--b;
}
void operator --(int)
{
a--;
b--;
}
};
int main()
{
pp p,p1;
cout<<"Before prefix decrement";
p.show();
--p;
cout<<"\nAfter prefix decrement";
p.show();
cout<<"\nBefore postfix decrement";
p1.show();
p1--;
cout<<"\nAfter postfix decrement";
p1.show();
}
(ii) Explain any two types of inheritance supported in C++ with suitable examples.
C++ Multilevel Inheritance
In C++ programming, not only you can derive a class from the base class but you can also derive
a class from the derived class. This form of inheritance is known as multilevel inheritance.
class A
{
... .. ...
};
class B: public A
{
... .. ...
};
class C: public B
{
... ... ...
};
Here, class B is derived from the base class A and the class C is derived from the derived
class B.
Example 1: C++ Multilevel Inheritance
#include <iostream>
using namespace std;
class A
{
public:
void display()
{
cout<<"Base class content.";
}
};
class B : public A
{
};
class C : public B
{
};
int main()
{
C obj;
obj.display();
return 0;
}
Output
Base class content.
In this program, class C is derived from class B (which is derived from base class A).
The obj object of class C is defined in the main() function.
When the display() function is called, display() in class A is executed. It's because there is
no display() function in class C and class B.
The compiler first looks for the display() function in class C. Since the function doesn't exist
there, it looks for the function in class B (as C is derived from B).
The function also doesn't exist in class B, so the compiler looks for it in classA (as B is derived
from A).
If display() function exists in C, the compiler overrides display() of class A(because of member
function overriding).
C++ Multiple Inheritance
In C++ programming, a class can be derived from more than one parents. For example: A
class Bat is derived from base classes Mammal and WingedAnimal. It makes sense because bat
is a mammal as well as a winged animal.
Example 2: Multiple Inheritance in C++ Programming
This program calculates the area and perimeter of an rectangle but, to perform this program,
multiple inheritance is used.
#include <iostream>
using namespace std;
class Mammal {
public:
Mammal()
{
cout << "Mammals can give direct birth." << endl;
}
};
class WingedAnimal {
public:
WingedAnimal()
{
cout << "Winged animal can flap." << endl;
}
};
class Bat: public Mammal, public WingedAnimal {
};
int main()
{
Bat b1;
return 0;
}
12. (a) Describe in detail dynamic memory allocation in C++ with examples. (13) [N/D-
16] [M/J – 15]
C++ Dynamic Memory
A good understanding of how dynamic memory really works in C++ is essential to becoming a
good C++ programmer. Memory in your C++ program is divided into two parts:
The stack: All variables declared inside the function will take up memory from the
stack.
The heap: This is unused memory of the program and can be used to allocate the
memory dynamically when program runs.
Many times, you are not aware in advance how much memory you will need to store particular
information in a defined variable and the size of required memory can be determined at run
time.
You can allocate memory at run time within the heap for the variable of a given type using a
special operator in C++ which returns the address of the space allocated. This operator is
callednew operator.
If you are not in need of dynamically allocated memory anymore, you can use delete operator,
which de-allocates memory previously allocated by new operator.
The new and delete operators
There is following generic syntax to use new operator to allocate memory dynamically for any
data-type.
new data-type;
Here, data-type could be any built-in data type including an array or any user defined data
types include class or structure. Let us start with built-in data types. For example we can define
a pointer to type double and then request that the memory be allocated at execution time. We
can do this using the new operator with the following statements:
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable
The memory may not have been allocated successfully, if the free store had been used up. So it
is good practice to check if new operator is returning NULL pointer and take appropriate action
as below:
double* pvalue = NULL;
if( !(pvalue = new double )) {
cout << "Error: out of memory." <<endl;
exit(1);
}
The malloc() function from C, still exists in C++, but it is recommended to avoid using malloc()
function. The main advantage of new over malloc() is that new doesn't just allocate memory, it
constructs objects which is prime purpose of C++.
At any point, when you feel a variable that has been dynamically allocated is not anymore
required, you can free up the memory that it occupies in the free store with the delete operator
as follows:
delete pvalue; // Release memory pointed to by pvalue
Let us put above concepts and form the following example to show how new and delete work:
#include <iostream>
using namespace std;
int main () {
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable
*pvalue = 29494.99; // Store value at allocated address
cout << "Value of pvalue : " << *pvalue << endl;
delete pvalue; // free up the memory.
return 0;
}
If we compile and run above code, this would produce the following result:
Value of pvalue : 29495
Dynamic Memory Allocation for Arrays
Consider you want to allocate memory for an array of characters, i.e., string of 20 characters.
Using the same syntax what we have used above we can allocate memory dynamically as
shown below.
char* pvalue = NULL; // Pointer initialized with null
pvalue = new char[20]; // Request memory for the variable
To remove the array that we have just created the statement would look like this:
delete [] pvalue; // Delete array pointed to by pvalue
Following is the syntax of new operator for a multi-dimensional array as follows:
int ROW = 2;
int COL = 3;
double **pvalue = new double* [ROW]; // Allocate memory for rows
// Now allocate memory for columns
for(int i = 0; i < COL; i++) {
pvalue[i] = new double[COL];
}
The syntax to release the memory for multi-dimensional will be as follows:
for(int i = 0; i < ROW; i++) {
delete[] pvalue[i];
}
delete [] pvalue;
Dynamic Memory Allocation for Objects
Objects are no different from simple data types. For example, consider the following code
where we are going to use an array of objects to clarify the concept:
#include <iostream>
using namespace std;
class Box {
public:
Box() {
cout << "Constructor called!" <<endl;
}
~Box() {
cout << "Destructor called!" <<endl;
}
};
int main( ) {
Box* myBoxArray = new Box[4];
delete [] myBoxArray; // Delete array
return 0;
}
If you were to allocate an array of four Box objects, the Simple constructor would be called four
times and similarly while deleting these objects, destructor will also be called same number of
times.
If we compile and run above code, this would produce the following result:
Constructor called!
Constructor called!
Constructor called!
Constructor called!
Destructor called!
Destructor called!
Destructor called!
Destructor called!
(b) Explain the types of inheritance in detail. [N/D-16] [N/D-15]
Inheritance is a mechanism of acquiring the features and behaviors of a class by another class.
The class whose members are inherited is called the base class, and the class that inherits those
members is called the derived class. Inheritance implements the IS-A relationship.
For example, mammal IS-A animal, dog IS-A mammal; Hence dog IS-A animal as well.
Types of Inheritance
In C++, we have 5 different types of Inheritance. Namely,
1. Single Inheritance
2. Multiple Inheritance
3. Hierarchical Inheritance
4. Multilevel Inheritance
5. Hybrid Inheritance (also known as Virtual Inheritance)
Single Inheritance
In this type of inheritance one derived class inherits from only one base class. It is the most
simplest form of Inheritance.
//Base Class
class A
{
public void fooA()
{
//TO DO:
}
}
//Derived Class
class B : A
{
public void fooB()
{
//TO DO:
}
}
Multiple Inheritance
In this type of inheritance a single derived class may inherit from two or more than two base
classes.
//Base Class
class A
{
public void fooA()
{
//TO DO:
}
}
//Base Class
class B
{
public void fooB()
{
//TO DO:
}
}
//Derived Class
class C : A, B
{
public void fooC()
{
//TO DO:
}
}
Hierarchical Inheritance
In this type of inheritance, multiple derived classes inherits from a single base class.
//Base Class
class A
{
public void fooA()
{
//TO DO:
}
}
//Derived Class
class B : A
{
public void fooB()
{
//TO DO:
}
}
//Derived Class
class C : A
{
public void fooC()
{
//TO DO:
}
}
//Derived Class
class D : C
{
public void fooD()
{
//TO DO:
}
}
//Derived Class
class E : C
{
public void fooE()
{
//TO DO:
}
}
//Derived Class
class F : B
{
public void fooF()
{
//TO DO:
}
}
//Derived Class
class G :B
{
public void fooG()
{
//TO DO:
}
}
Multilevel Inheritance
In this type of inheritance the derived class inherits from a class, which in turn inherits from
some other class. The Super class for one, is sub class for the other.
//Base Class
class A
{
public void fooA()
{
//TO DO:
}
}
//Derived Class
class B : A
{
public void fooB()
{
//TO DO:
}
}
//Derived Class
class C : B
{
public void fooC()
{
//TO DO:
}
}
Hybrid (Virtual) Inheritance
Hybrid Inheritance is combination of Hierarchical and Mutilevel Inheritance.
//Base Class
class A
{
public void fooA()
{
//TO DO:
}
}
//Base Class
class F
{
public void fooF()
{
//TO DO:
}
}
//Derived Class
class B : A, F
{
public void fooB()
{
//TO DO:
}
}
//Derived Class
class C : A
{
public void fooC()
{
//TO DO:
}
}
//Derived Class
class D : C
{
public void fooD()
{
//TO DO:
}
}
//Derived Class
class E : C
{
public void fooE()
{
//TO DO:
}
}
(ii) List the rules associated with operator overloading? What are the operators that cannot be
overloaded? Write a program to overload any one of the binary operators? (8) [M/J – 15]
Rules for Overloading Operators
Only existing operators can be overloaded. New operators cannot be created.
The overloaded operator must have atleast one operand that is of user defined type.
The basic meaning of an operator cannot be changed. That is the plus operator cannot be
used to subtract one value from the other.
Overloaded operator follow the syntax rules of the original operators. They cannot be
overridden.
There are some operators that cannot be overloaded. They are Size of, . ,: :,?:.
Friend function cannot be used to overload certain operators ( = ,( ) ,[ ] ,->).However
member functions can be used to overload them.
Unary operators, overload by means of a member function, take no explicit arguments
and return no explicit values,but,those overloaded by means of a friend function, take one
reference argument.
Binary operators overloaded through a member function take one explicit argument and
those which are overloaded through a friend function take two explicit arguments.
When using binary operator overloaded through a member function, the left hand
operand must be an object of the relevant class.
Binary arithmetic operators such as +,-,*,and / must explicitly return a value. They must
not attempt to change their own arguments.
List of operators that cannot be overloaded.
?: (conditional)
. ( member selection)
.* (member selection with pointer-to-member)
:: (scope resolution)
sizeof (object size information)
typeid (object type information)
#include<iostream.h>
#include<conio.h>
class complex
{
int a,b;
public:
void getvalue()
{
cout<<"Enter the value of Complex Numbers a,b:";
cin>>a>>b;
}
complex operator+(complex ob)
{
complex t;
t.a=a+ob.a;
t.b=b+ob.b;
return(t);
}
complex operator-(complex ob)
{
complex t;
t.a=a-ob.a;
t.b=b-ob.b;
return(t);
}
void display()
{
cout<<a<<"+"<<b<<"i"<<"\n";
}
};
void main()
{
clrscr();
complex obj1,obj2,result,result1;
obj1.getvalue();
obj2.getvalue();
result = obj1+obj2;
result1=obj1-obj2;
cout<<"Input Values:\n";
obj1.display();
obj2.display();
cout<<"Result:";
result.display();
result1.display();
getch();
}
Output:
Enter the value of Complex Numbers a, b
4 5
Enter the value of Complex Numbers a, b
2 2
Input Values
4 + 5i
2 + 2i
Result
6 + 7i
2 + 3i
(ii) Define a class Area to identify the area of square and rectangle using constructor and
destructor. Use the parameters length(l) and breadth (b) for the constructor functions.
// using C++ class instead of struct with constructor and destructor
#include <iostream>
using namespace std;
// A simple class declaration
class rectangle
{
// private access by default, access only through the method or interface
int height;
int width;
// public
public:
// constructor, initial object construction, allocating storage, initial value etc.
rectangle(void);
// methods, access something, do something
int area(void);
void initialize(int, int);
// destructor, destroy all the object, return resources such as memory etc. to the system
~rectangle(void);
};
// class implementation
// constructor implementation
rectangle::rectangle(void)
{
// give initial values
height = 6;
width = 6;
}
int rectangle::area(void)
{
// just return the area
return (height * width);
}
void rectangle::initialize(int initial_height, int initial_width)
{
// give initial values
height = initial_height;
width = initial_width;
}
// destructor implementation
rectangle::~rectangle(void)
{
// destroy all the object an return the resources to the system
height = 0;
width = 0;
}
// normal structure - compare with class usage
struct pole
{
int length;
int depth;
};
// comes the main()
void main(void)
{
// class object instantiations
rectangle wall, square;
// normal struct
pole lamp_pole;
cout<<"Check the size of rectangle = "<<sizeof(rectangle)<<" bytes"<<endl;
cout<<"Check the size of pole = "<<sizeof(pole)<<" bytes"<<endl<<endl;
cout<<"Using class instead of struct, using DEFAULT VALUE"<<endl;
cout<<"supplied by constructor, access through area() method"<<endl;
cout<<"----------------------------------------------------"<<endl<<endl;
cout<<"Area of the wall, wall.area() = "<<wall.area()<<endl;
cout<<"Area of the square, square.area() = "<<square.area()<<endl<<endl;
// we can override the constructor values
wall.initialize(12, 10);
square.initialize(8,8);
cout<<"Using class instead of struct, USING ASSIGNED VALUE, access through area()
method"<<endl;
cout<<"---------------------------------------------------------------------------------"<<endl;
cout<<"Area of the wall, wall.area() = "<<wall.area()<<endl;
cout<<"Area of the square, square.area()= "<<square.area()<<endl<<endl;
lamp_pole.length = 50;
lamp_pole.depth = 6;
cout<<"Just a comparison to the class, the following is a struct"<<endl;
cout<<"The length of the lamp pole is = "<<lamp_pole.length*lamp_pole.depth<<endl<<endl;
}
Output example:
Check the size of rectangle = 8 bytes
Check the size of pole = 8 bytes
Using class instead of struct, using DEFAULT VALUE
supplied by constructor, access through area() method
----------------------------------------------------
Area of the wall, wall.area() = 36
Area of the square, square.area() = 36
Using class instead of struct, USING ASSIGNED VALUE, access through area() method
---------------------------------------------------------------------------------
Area of the wall, wall.area() = 120
Area of the square, square.area()= 64
Just a comparison to the class, the following is a struct
The length of the lamp pole is = 300
(ii) Distinguish the term overloading and overriding. (4) [N/D-15]
Overriding Overloading
Methods name and signatures must be same. Having same method name with different
Signatures.
Overriding is the concept of runtime
polymorphism
Overloading is the concept of compile time
polymorphism
When a function of base class is re-defined in
the derived class called as Overriding
Two functions having same name and return
type, but with different type and/or number of
arguments is called as Overloading
It needs inheritance. It doesn't need inheritance.
Method should have same data type. Method can have different data types
Method should be public. Method can be different access specifies
Example
Overriding
public class MyBaseClass
{
public virtual void MyMethod()
{
Console.Write("My BaseClass Method");
}
}
public class MyDerivedClass : MyBaseClass
{
public override void MyMethod()
{
Console.Write("My DerivedClass Method");
}
}
Overloading
int add(int a, int b)
int add(float a , float b) Overloading is defining functions that have similar signatures, yet have
different parameters.
Overriding is only pertinent to derived classes, where the parent class has defined a method and
the derived class wishes to override that function.
Example
Overriding
public class MyBaseClass
{
public virtual void MyMethod()
{
Console.Write("My BaseClass Method");
}
}
public class MyDerivedClass : MyBaseClass
{
public override void MyMethod()
{
Console.Write("My DerivedClass Method");
}
}
Overloading
int add(int a, int b)
int add(float a , float b)
(b) (i) Write a C++ program to explain how the run time polymorphism is achieved.
#include<iostream>
using namespace std;
class B // Base class
{
public:
virtual void Display(void) // virtual function
{
cout << "\n The member function Display( ) " ;
cout << "of the \"Base Class B\" is invoked \n" ;
}
};
class D1 : public B // First derived class
{
public:
void Display(void)
{
cout << "\n The member function Display( ) " ;
cout << "of the \"Derived Class D1\" is invoked \n" ;
}
};
class D2 : public B // Second derived class
{
public:
void Display(void)
{
cout << "\n The member function Display() " ;
cout << "of the \"Derived Class D2\" is invoked " ;
}
};
int main()
{
B* base_ptr ; // Pointer to the object of the base class
D1 der1_obj ; // Object of the first derived class D1
base_ptr = &der1_obj ; /* The address of the object der1_obj of the
first derived class D1 is assigned to the
pointer base_ptr of the base class B */
base_ptr->Display( ); // Accessing the member function Display( )
D2 der2_obj ; // Object of the second derived class D2
base_ptr = &der2_obj ; /* The address of the object der2_obj of the
second derived class D2 is assigned to the
pointer base_ptr of the base class B */
base_ptr->Display( ); // Accessing the member function Display( )
return 0;
}
12. (a) (i) Write a program to perform string copy operation using dynamic
constructor.
(6) [N/D-14]
# include <iostream.h>
# include <conio.h>
# include <string.h>
class str
{
char *name;
int len;
public:
str()
{
len=0;
name=newchar[len+1];
}
str(char *s)
{
len=strlen(s);
name=newchar[len+1];
strcpy(name,s);
}
void show()
{
cout<<"NAME IS:->"<<name<<endl;
}
void join(str &a,str &b);
};
void str::join(str &a,str &b)
{
len=a.len+b.len;
delete new;
name=newchar[len+1];
strcpy(name,a.name);
strcat(name,b.name);
};
main()
{
clrscr();
char *first="HARSHIL";
str n1(first),n2("NINAD"),n3("PRATIK"),n4,n5;
n4.join(n1,n2);
n5.join(n4,n3);
n1.show();
n2.show();
n3.show();
n4.show();
n5.show();
}
(b) (i) Write a program to perform dvnamic initialization of objects. (6) [N/D-
14]
Dynamic Initialization of objects:
It is initializing the objects by passing the valued to the constructor from the user input or
other means. Through cin operator a value can be stored in a variable and passed through a
constructor this form of initializing an object is known dynamic initialization.
Dynamic Constructor:
The memory allocation for a constructor can be managed using new operator called new,
similarly the memory can be free with another operator called deleter.
class dynmem
{ char *name;
int length;
public:
dynmem(void)
{length =0;
name = new char[length+1];
}
dynmem(char *s)
{length = strlen(s);
name = new char[length+1];//for null terminator
strcpy(name,s);
}
void display(void)
{cout<
}
void join(dynmem &a, dynmem &b);
};
void dynmem::join(dynmem &a, dynmem &b)
{length = a.length+b.length;
delete name;
name = new char[length+1]; strcpy(name,a.name); strcat(name,b.name);
};
void main()
{
clrscr();
char *first="Electronic ";
dynmem name1(first);
dynmem name2("and Communication ");
dynmem name3("Engineering"); dynmem s1,s2; s1.join(name1,name2); s2.join(s1,name3);
name1.display();