Good Questions In
C++
!!Enjoy!!!
25.
What is the purpose of istream class?
Ans: The istream class performs activities specific to input.
It is derived from the ios class. The most commonly used
member function of this class is the overloaded >> operator
which can extract values of all basic types. We can extract
even a string using this operator.
-------------------------------------------------------------------------------------------------
26.
Would the following code work?
#include <iostream.h>
void main( )
{
ostream o ;
o << "Dream. Then make it happen!" ;
}
Ans: No! This is because we cannot create an object of the
ostream class since its constructor and copy constructor are
declared private.
-------------------------------------------------------------------------------------------------
27.
Can we use this pointer inside static member function?
Ans: No! The this pointer cannot be used inside a static
member function. This is because a static member function is
never called through an object.
-------------------------------------------------------------------------------------------------
28.
What is strstream?
Ans: strstream is a type of input/output stream that works
with the memory. It allows using section of the memory as a
stream object. These streams provide the classes that can be
used for storing the stream of bytes into memory. For example,
we can store integers, floats and strings as a stream of
bytes. There are several classes that implement this in-memory
formatting. The class ostrstream derived from ostream is used
when output is to be sent to memory, the class istrstream
derived from istream is used when input is taken from memory
and strstream class derived from iostream is used for
memory objects that do both input and output.
-------------------------------------------------------------------------------------------------
29.
Ans: When we want to retrieve the streams of bytes from memory
we can use istrestream. The following example shows the use of
istrstream class.
#include <strstream.h>
void main( )
{
int age ;
float salary ;
char name[50] ;
char str[] = "22 12004.50 K. Vishwanatth" ;
istrstream s ( str ) ;
s >> age >> salary >> name ;
cout << age << endl << salary << endl << name ;
cout << endl << s.rdbuf( ) ;
}
Here, s is the object of the class istrstream. When we are
creating the object s, the constructor of istrstream gets
called that receives a pointer to the zero terminated
character array str. The statement s >> age >> salary >> name
; extracts the age, salary and the name from the istrstream
object s. However, while extracting the name, only the first
word of name gets extracted. The balance is extracted using
rdbuf( ).
-------------------------------------------------------------------------------------------------
30.
When the constructor of a base class calls a virtual function,
why doesn't the override function of the derived class gets
called?
Ans: While building an object of a derived class first the
constructor of the base class and then the constructor of the
derived class gets called. The object is said an immature
object at the stage when the constructor of base class is
called. This object will be called a matured object after the
execution of the constructor of the derived class. Thus, if we
call a virtual function when an object is still immature,
obviously, the virtual function of the base class would get
called. This is illustrated in the following example.
#include <iostream.h>
class base
{
protected :
int i ;
public :
base ( int ii = 0 )
{
i = ii ;
show( ) ;
}
virtual void show( )
{
cout << "base's show( )" << endl ;
}
} ;
class derived : public base
{
private :
int j ;
public :
derived ( int ii, int jj = 0 ) : base ( ii )
{
j = jj ;
show( ) ;
}
void show( )
{
cout << "derived's show( )" << endl ;
}
} ;
void main( )
{
derived dobj ( 20, 5 ) ;
}
The output of this program would be:
base's show( )
derived's show( )
-------------------------------------------------------------------------------------------------
31.
Can I have a reference as a data member of a class? If yes,
then how do I initialise it?
Ans: Yes, we can have a reference as a data member of a class.
A reference as a data member of a class is initialised in the
initialisation list of the constructor. This is shown in
following program.
#include <iostream.h>
class sample
{
private :
int& i ;
public :
sample ( int& ii ) : i ( ii )
{
}
void show( )
{
cout << i << endl ;
}
} ;
void main( )
{
int j = 10 ;
sample s ( j ) ;
s.show( ) ;
}
Here, i refers to a variable j allocated on the stack. A point
to note here is that we cannot bind a reference to an object
passed to the constructor as a value. If we do so, then the
reference i would refer to the function parameter (i.e.
parameter ii in the constructor), which would disappear as
soon as the function returns, thereby creating a situation of
dangling reference.
-------------------------------------------------------------------------------------------------
32.
Why does the following code fail?
#include <string.h>
class sample
{
private :
char *str ;
public :
sample ( char *s )
{
strcpy ( str, s ) ;
}
~sample( )
{
delete str ;
}
} ;
void main( )
{
sample s1 ( "abc" ) ;
}
Ans: Here, through the destructor we are trying to deal locate
memory, which has been allocated statically. To remove an
exception, add following statement to the constructor.
sample ( char *s )
{
str = new char[strlen(s) + 1] ;
strcpy ( str, s ) ;
}
Here, first we have allocated memory of required size, which
then would get deal located through the destructor.
-------------------------------------------------------------------------------------------------
33.
assert( ) macro...
We can use a macro called assert( ) to test for conditions
that should not occur in a code. This macro expands to an if
statement. If test evaluates to 0, assert prints an error
message and calls abort to abort the program.
#include <iostream.h>
#include <assert.h>
void main( )
{
int i ;
cout << "\nEnter an integer: " ;
cin >> i ;
assert ( i >= 0 ) ;
cout << i << endl ;
}
-------------------------------------------------------------------------------------------------
34.
Why it is unsafe to deal locate the memory using free( ) if it
has been allocated using new?
Ans: This can be explained with the following example:
#include <malloc.h>
class sample
{
int *p ;
public :
sample( )
{
p = new int ;
}
~sample( )
{
delete p ;
}
} ;
void main( )
{
sample *s1 = new sample ;
free ( s1 ) ;
sample *s2 = ( sample * ) malloc ( sizeof ( sample
) ) ;
delete s2 ;
}
The new operator allocates memory and calls the constructor.
In the constructor we have allocated memory on heap, which is
pointed to by p. If we release the object using the free( )
function the object would die but the memory allocated in the
constructor would leak. This is because free( ) being a C
library function does not call the destructor where we have
deal located the memory.
As against this, if we allocate memory by calling malloc( )
the constructor would not get called. Hence p holds a garbage
address. Now if the memory is deal located using delete, the
destructor would get called where we have tried to release the
memory pointed to by p. Since p contains garbage this may
result in a runtime error.
-------------------------------------------------------------------------------------------------
35.
Can we distribute function templates and class templates in
object libraries?
Ans: No! We can compile a function template or a class
template into object code (.obj file). The code that contains
a call to the function template or the code that creates an
object from a class template can get compiled. This is because
the compiler merely checks whether the call matches the
declaration (in case of function template) and whether the
object definition matches class declaration (in case of class
template). Since the function template and the class template
definitions are not found, the compiler leaves it to the
linker to restore this. However, during linking, linker
doesn't find the matching definitions for the function call or
a matching definition for object creation. In short the
expanded versions of templates are not found in
the object library. Hence the linker reports error.
-------------------------------------------------------------------------------------------------
36.
What is the difference between an inspector and a mutator ?
Ans: An inspector is a member function that returns
information about an object's state (information stored in
object's data members) without changing the object's state. A
mutator is a member function that changes the state of an
object. In the class Stack given below we have defined a
mutator and an inspector.
class Stack
{
public :
int pop( ) ;
int getcount( ) ;
}
In the above example, the function pop( ) removes top element
of stack thereby changing the state of an object. So, the
function pop( ) is a mutator. The function getcount( ) is an
inspector because it simply counts the number of elements in
the stack without changing the stack.
-------------------------------------------------------------------------------------------------
37.
Namespaces:
The C++ language provides a single global namespace. This can
cause problems with global name clashes. For instance,
consider these two C++ header files:
// file1.h
float f ( float, int ) ;
class sample { ... } ;
// file2.h
class sample { ... } ;
With these definitions, it is impossible to use both header
files in a single program; the sample classes will clash.A
namespace is a declarative region that attaches an additional
identifier to any names declared inside it. The additional
identifier thus avoids the possibility that a name will
conflict with names declared elsewhere in the program. It is
possible to use the same name in separate namespaces without
conflict even if the names appear in the same translation
unit. As long as they appear in separate namespaces, each name
will be unique because of the addition of the namespace
identifier. For example:
// file1.h
namespace file1
{
float f ( float, int ) ;
class sample { ... } ;
}
// file2.h
namespace file2
{
class sample { ... } ;
}
Now the class names will not clash because they become
file1::sample and file2::sample, respectively.
-------------------------------------------------------------------------------------------------
38.
What would be the output of the following program?
#include <iostream.h>
class user
{
int i ;
float f ;
char c ;
public :
void displaydata( )
{
cout << endl << i << endl << f << endl << c ;
}
} ;
void main( )
{
cout << sizeof ( user ) ;
user u1 ;
cout << endl << sizeof ( u1 ) ;
u1.displaydata( ) ;
}
Ans: The output of this program would be,
9 or 7
9 or 7
Garbage
Garbage
Garbage
Since the user class contains three elements, int, float and
char its size would be 9 bytes (int-4, float-4, char-1) under
Windows and 7 bytes (int-2, float-4, char-1) under DOS. Second
output is again the same because u1 is an object of the class
user. Finally three garbage values are printed out because i,
f and c are not initialized anywhere in the program.
Note that if you run this program you may not get the answer
shown here. This is because packing is done for an object in
memory to increase the access efficiency. For example, under
DOS, the object would be aligned on a 2-byte boundary. As a
result, the size of the object would be reported as 6 bytes.
Unlike this, Windows being a 32-bit OS the object would be
aligned on a 4-byte boundary. Hence the size of the object
would be reported as 12 bytes. To force the alignment on a
1-byte boundary, write the following statement before the
class declaration.
#pragma pack ( 1 )
-------------------------------------------------------------------------------------------------
39.
Write a program that will convert an integer pointer to an
integer and vice-versa.
Ans: The following program demonstrates this.
#include <iostream.h>
void main( )
{
int i = 65000 ;
int *iptr = reinterpret_cast <int *> ( i ) ;
cout << endl << iptr ;
iptr++ ;
cout << endl << iptr ;
i = reinterpret_cast <int> ( iptr ) ;
cout << endl << i ;
i++ ;
cout << endl << i ;
}
-------------------------------------------------------------------------------------------------
40.
What is a const_cast?
Ans. The const_cast is used to convert a const to a non-const.
This is shown in the following
program:
#include <iostream.h>
void main( )
{
const int a = 0 ;
int *ptr = ( int * ) &a ; //one way
ptr = const_cast_ <int *> ( &a ) ; //better way
}
Here, the address of the const variable a is assigned to the
pointer to a non-const variable. The const_cast is also used
when we want to change the data members of a class inside the
const member functions. The following code snippet shows this:
class sample
{
private:
int data;
public:
void func( ) const
{
(const_cast <sample * >(this))->data = 70 ;
}
} ;
-------------------------------------------------------------------------------------------------
41.
What is forward referencing and when should it be used?
Ans: Forward referencing is generally required when we make a
class or a function as a friend.
Consider following program:
class test
{
public:
friend void fun ( sample, test ) ;
} ;
class sample
{
public:
friend void fun ( sample, test ) ;
} ;
void fun ( sample s, test t )
{
// code
}
void main( )
{
sample s ;
test t ;
fun ( s, t ) ;
}
On compiling this program it gives error on the following
statement of test class. It gives an error that sample is
undeclared identifier. friend void fun ( sample, test ) ;
This is so because the class sample is defined below the class
test and we are using it before its definition. To overcome
this error we need to give forward reference of the class
sample before the definition of class test. The following
statement is the forward reference of class sample.
class sample ;
-------------------------------------------------------------------------------------------------
42.
How would you give an alternate name to a namespace?
Ans: An alternate name given to namespace is called a
namespace-alias. namespace-alias is generally used to save the
typing effort when the names of namespaces are very long or
complex. The following syntax is used to give an alias to a
namespace.
namespace myname = my_old_very_long_name ;
-------------------------------------------------------------------------------------------------
43.
Using a smart pointer can we iterate through a container?
Ans: Yes. A container is a collection of elements or objects.
It helps to properly organize and store the data. Stacks,
linked lists, arrays are examples of containers. Following
program shows how to iterate through a container using a smart
pointer.
#include <iostream.h>
class smartpointer
{
private :
int *p ; // ordinary pointer
public :
smartpointer ( int n )
{
p = new int [ n ] ;
int *t = p ;
for ( int i = 0 ; i <= 9 ; i++ )
*t++ = i * i ;
}
int* operator ++ ( int )
{
return p++ ;
}
int operator * ( )
{
return *p ;
}
} ;
void main( )
{
smartpointer sp ( 10 ) ;
for ( int i = 0 ; i <= 9 ; i++ )
cout << *sp++ << endl ;
}
Here, sp is a smart pointer. When we say *sp, the operator * (
) function gets called. It returns the integer being pointed
to by p. When we say sp++ the operator ++ ( ) function gets
called. It increments p to point to
the next element in the array and then returns the address of
this new location.
-------------------------------------------------------------------------------------------------
44.
Can objects read and write themselves?
Ans: Yes! This can be explained with the help of following
example:
#include <fstream.h>
#include <iostream.h>
class employee
{
private :
char name [ 20 ] ;
int age ;
float salary ;
public :
void getdata( )
{
cout << "Enter name, age and salary of employee : " ;
cin >> name >> age >> salary ;
}
void store( )
{
ofstream file ;
file.open ( "EMPLOYEE.DAT", ios::app | ios::binary ) ;
file.write ( ( char * ) this, sizeof ( *this ) ) ;
file.close( ) ;
}
void retrieve ( int n )
{
ifstream file ;
file.open ( "EMPLOYEE.DAT", ios::binary ) ;
file.seekg ( n * sizeof ( employee ) ) ;
file.read ( ( char * ) this, sizeof ( *this ) ) ;
file.close( ) ;
}
void show( )
{
cout << "Name : " << name
<< endl << "Age : " << age
<< endl << "Salary :" << salary << endl ;
}
} ;
void main( )
{
employee e [ 5 ] ;
for ( int i = 0 ; i <= 4 ; i++ )
{
e [ i ].getdata( ) ;
e [ i ].store( ) ;
}
for ( i = 0 ; i <= 4 ; i++ )
{
e [ i ].retrieve ( i ) ;
e [ i ].show( ) ;
}
}
Here, employee is the class whose objects can write and read
themselves. The getdata( ) function has been used to get the
data of employee and store it in the data members name, age
and salary. The store( ) function is used to write an object
to the file. In this function a file has been opened in append
mode and each time data of current object has been stored
after the last record (if any) in the file.Function retrieve(
) is used to get the data of a particular employee from the
file. This retrieved data has been stored in the data members
name, age and salary. Here this has been used to store data
since it contains the address of the current object. The
function show( ) has been used to display the data of
employee.
-------------------------------------------------------------------------------------------------
45.
Why is it necessary to use a reference in the argument to the
copy constructor?
Ans : If we pass the copy constructor the argument by value,
its copy would get constructed using the copy constructor.
This means the copy constructor would call itself to make this
copy. This process would go on and on until the compiler runs
out of memory. This can be explained with the help of
following example:
class sample
{
int i ;
public :
sample ( sample p )
{
i = p.i ;
}
} ;
void main( )
{
sample s ;
sample s1 ( s ) ;
}
While executing the statement sample s1 ( s ), the copy
constructor would get called. As the copy construct here
accepts a value, the value of s would be passed which would
get collected in p. We can think of this statement as sample p
= s. Here p is getting created and initialized. Means again
the copy constructor would get called. This would result into
recursive calls. Hence we must use a reference as an argument
in a copy constructor.
-------------------------------------------------------------------------------------------------
46.
Virtual Multiple Inheritance:
A class b is defined having member variable i. Suppose two
classes d1 and d2 are derived from class b and a class
multiple is derived from both d1 and d2. If variable i is
accessed from a member function of multiple then it gives
error as 'member is ambiguous'. To avoid this error derive
classes d1 and d2 with modifier virtual as shown in the
following program.
#include <iostream.h>
class b
{
public :
int i ;
public :
fun( )
{
i = 0 ;
}
} ;
class d1 : virtual public b
{
public :
fun( )
{
i = 1 ;
}
} ;
class d2 : virtual public b
{
public :
fun( )
{
i = 2 ;
}
} ;
class multiple : public d1, public d2
{
public :
fun( )
{
i = 10 ;
}
} ;
void main( )
{
multiple d ;
d.fun( ) ;
cout << d.i ;
}
-------------------------------------------------------------------------------------------------
47.
Can we use this pointer in a class specific,
operator-overloading function for new operator?
Ans: No! The this pointer is never passed to the overloaded
operator new() member function because this function gets
called before the object is created. Hence there is no
question of the this pointer getting passed to operator new(
).
-------------------------------------------------------------------------------------------------
48.
Can we allocate memory dynamically for a reference?
Ans: No! It is not possible to allocate memory dynamically for
a reference. This is because, when we create a reference, it
gets tied with some variable of its type. Now, if we try to
allocate memory dynamically for a reference, it is not
possible to mention that to which variable the reference would
get tied.
-------------------------------------------------------------------------------------------------
49.
When should I overload new operator on a global basis or a
class basis?
Ans: We overload operator new in our program, when we want to
initialize a data item or a class object at the same place
where it has been allocated memory. The following example
shows how to overload new operator on global basis.
#include <iostream.h>
#include <malloc.h>
void * operator new ( size_t s )
{
void *q = malloc ( s ) ;
return q ;
}
void main( )
{
int *p = new int ;
*p = 25 ;
cout << *p ;
}
When the operator new is overloaded on global basis it becomes
impossible to initialize the data members of a class as
different classes may have different types of data members.
The following example shows how to
overload new operator on class-by-class basis.
#include <iostream.h>
#include <malloc.h>
class sample
{
int i ;
public :
void* operator new ( size_t s, int ii )
{
sample *q = ( sample * ) malloc ( s ) ;
q -> i = ii ;
return q ;
}
} ;
class sample1
{
float f ;
public :
void* operator new ( size_t s, float ff )
{
sample1 *q = ( sample1 * ) malloc ( s ) ;
q -> f = ff ;
return q ;
}
} ;
void main( )
{
sample *s = new ( 7 ) sample ;
sample1 *s1 = new ( 5.6f ) sample1 ;
}
Overloading the operator new on class-by-class basis makes it
possible to allocate memory for an object and initialize its
data members at the same place.
-------------------------------------------------------------------------------------------------
50.
How would you define a pointer to a data member of the type
pointer to pointer?
Ans: The following program demonstrates this...
#include <iostream.h>
class sample
{
public :
sample ( int **pp )
{
p = pp ;
}
int **p ;
} ;
int **sample::*ptr = &sample::p ;
void main( )
{
int i = 9 ;
int *pi = &i ;
sample s ( &pi ) ;
cout << ** ( s.*ptr ) ;
}
Here, ptr is the pointer to data member p of class sample,
which in turn is a pointer pointing to an int.
-------------------------------------------------------------------------------------------------
51.
How do I write a code to catch multiple types of exceptions in
one single catch block?
Ans: The following program demonstrates the use of a single
catch block to catch multiple exceptions.
#include <iostream.h>
class test
{
} ;
class sample
{
public :
void fun1( )
{
throw 99 ;
}
void fun2( )
{
throw 3.14f ;
}
void fun3( )
{
throw "error" ;
}
void fun4( )
{
throw test( ) ;
}
} ;
void main( )
{
try
{
sample s ;
s.fun4( ) ;
s.fun1( ) ;
s.fun2( ) ;
s.fun3( ) ;
}
catch ( ... )
{
cout << "strange" ;
}
}
Here, different types of exceptions are thrown by the member
functions of the class sample. While catching the exception
instead of four different catch blocks we can as well define
one single catch block. Note the syntax for defining the catch
block, where we have used three dots (…) in the formal
parameter list. This indicates that any thrown exception
should get caught in the same catch block. When the exception
is thrown from the fun4( ) control reaches the catch block,
ignoring the rest of the calls.
-------------------------------------------------------------------------------------------------