Texas Instrument - Placement Paper - Interview Questions 5

Started by ganeshbala, Mar 14, 2008, 07:16 PM

Previous topic - Next topic

ganeshbala

91. What is name mangling?
Ans: C++ enables you to assign the same function name to more than one functions but with different parameter types. This feature is called function overloading. But when we give several functions the same name, how does the compiler decide which particular function is to be called? C++ solves this problem by applying a process called name mangling. Name mangling applies a decorated name to the function. The mangled name includes tokens that identify the functions' return type and the types of its arguments.
class test
{
public :
void fun ( int a, char b ) ;
void fun ( char *c, float y ) ;
} ;
void main( )
{
test s1 ;
s1.fun ( 65, 'A' ) ;
s1.fun ( "Anil", 5.5f ) ;
}
At the time of resolving the calls to fun( ) function the linker would not be able to find the definition of the overloaded function fun( ) and it would report an error. If you look at these errors you will see the mangled names like, (?fun@test@@QAEXJJ@Z) and (?fun@test@@QAEXMM@Z). Note that different compilers may use different name mangling schemes.

92. How would you call a C function from C++ code?
Ans: Using extern "C".
The function prototype must be preceded by extern "C". More than one C functions can be grouped inside braces as shown below:
extern "C"
{
void f( ) ;
void f1( ) ;
}
// In cfunc.c
#include
void f( )
{
printf ( "in f( )" ) ;
}
// In func.cpp
#include
extern "C" void f( ) ;
void main( )
{
f( ) ;
}
Ensure that both .c and .cpp files are in the same project.

93. How to restrict the number of floating-point digits displayed ?
Ans: When we display floating-point values, we can use the setprecision manipulator to specify the desired number of digits to the right of the decimal point.
For example,
cout << setprecision ( 3 ) << 12.34678 ;
This statement would give the output as 12.347.

94. What is a wild pointer ?
Ans: A wild pointer is the one that points to a garbage value. For example, an uninitialized pointer that contains garbage value or a pointer that refers to something that no longer exists.

95. How friend function helps to increase the versatility of overloaded operators?
Ans: Consider the following statement,
s2 = s1 * 2 ;
where, s1 and s2 are objects of sample class. This statement would work if the overloaded operator * ( sample s ) or conversion function is provided in the class. Internally this statement would get converted to,
s2 = s1.operator * ( 2 ) ;
The function materializes because it is called with an object s1. The this pointer of s1 would get passed implicitly. To collect 2 in s, first the compiler would call the one-argument constructor, then it would build a nameless object, which then would get collected in s. However, if we write the above statement as,
s2 = 2 * s1 ;
then it won't compile. This is because the call now would get treated as,
s2 = 2.operator * ( s1 ) ;
and 2 is not an object. The friend function helps to get rid of such a situation. This is shown in the following program.
#include
class sample
{
private :
int i ;
public :
sample ( int ii = 0 )
{
i = ii ;
}
void showdata( )
{
cout << i << endl ;
}
friend sample operator * ( sample, sample ) ;
} ;
sample operator * ( sample s1, sample s2 )
{
sample temp ;
temp.i = s1.i * s2.i ;
return ( temp ) ;
}
void main( )
{
sample s1 ( 10 ), s2 ;
s2 = s1 * 2 ;
s2.showdata( ) ;
s1 = 2 * s2 ;
s1.showdata( ) ;
}
Here the operator *( ) function takes two parameters. This is because the operator function is no longer a member function of the class. It is a friend of the class sample. Thus the statement s2 = s1 * 2 ; would not take the form s2.operator * ( 2 ). This example shows that using friend permits the overloaded operators to be more versatile.

96. 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
void main( )
{
const int a = 0 ;
int *ptr = ( int * ) &a ; // one way
ptr = const_cast ( &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 how to do this.
class sample
{
private :
int data ;
public :
void fun( ) const
{
( const_cast ( this ) ) -> data = 70 ;
}
} ;

97. Using a smart pointer we can make an object appear like a pointer.
If a class overloads the operator -> then any object of that class can appear like a pointer when the operator -> ( ) is called. The following program illustrates this.
#include
class test
{
public :
void fun( )
{
cout << "fun of smart pointer" ;
}
} ;
class smartpointer
{
test t ;
public :
test* operator ->( )
{
return &t ;
}
} ;
void main( )
{
smartpointer sp ;
sp -> fun( ) ;
}
The beauty of overloading operator -> is that even though sp is an object we can make it work like a pointer. The operator -> ( ) returns the address of the object of the type test. Using this address of the test object the function fun( ) of the class test gets called. Thus even though fun( ) is not a member of smartpointer class we can still call it using sp.

98. Can we apply delete on this pointer inside a member function?
Ans : Yes! If the member function of a class is called using a pointer to an object, which is allocated dynamically, the object would get deleted. But if the member function is called using the object, which is allocated statically, then a runtime error would occur. This is because we cannot call delete on statically allocated objects. This is illustrated in the following example.
class sample
{
private :
int i ;
public :
void fun( )
{
delete this ;
}
} ;
void main( )
{
sample *s = new sample ;
s -> fun( ) ; // no error

sample s1 ;
s1.fun( ) ; // would throw a runtime error
}

99. Why can't data members of a class be initialized at the time of declaration as given in the following code?
class emp
{
private :
int j = 10 ;
} ;
Ans: Memory for data members of a class is allocated only when object of
that class is created. One cannot store data in a memory location, which does not exist at all. Therefore initialization at the time of declaration is not possible.

100. Why in a copy constructor an object is collected in a reference to object as shown below?
#include
class emp
{
public :
emp( )
{
}
emp ( emp& )
{
cout << "copy" ;
}
} ;
void main( )
{
emp e ;
emp e1 = e ;
}
Ans: A copy constructor is called when an object is created and initialised at the same time. It is also called when object is passed to a function. So, If we pass the object to copy constructor copy constructor would get called recursively. Thus it will stuck up in an infinite loop.

101. What is Early Binding and Dynamic Binding?
Ans: The term binding refers to the connection between a function call and the actual code executed as a result of the call. Early Binding: If which function is to be called is known at the compile-time it is known as static or early binding. Dynamic Binding: If which function is to be called is decided at run time it is called as late or dynamic binding. Dynamic binding is so called because the actual function called at run-time depends on the contents of the pointer. For example, call to virtual functions, call to functions to be linked from dlls use late binding.

102. When can we use the function ostrstream::freeze( )?
Ans: While outputting data to memory in the in-memory formatting we need to create an object of the class ostrstream. The constructor of ostrstream receives the address of the buffer but if we want that the ostrstream object should do its own memory management then we need to create an ostrstream object with no constructor arguments as:
ostrstream s ;
Now s will do its own memory management. We can stuff as many bytes into it as we want. If it falls short of memory, it will allocate more memory. If it cannot, it may even move the block of memory. When the object goes out of scope, the heap storage is automatically released. This is a more flexible approach if we do not know how much space we are going to need. If we want the physical address of the memory used by s we can obtain it by calling the str( ) member function:
char* p = s.str( ) ;
Once str( ) has been called then the block of memory allocated by ostrstream cannot be moved. This is logical. It can't move the block since we are now expecting it to be at a particular location. In such a case we say that ostrstream has freezed itself. Once frozen we can't add any more characters to it. Adding characters to a frozen ostrstream results in undefined behavior. In addition, the ostrstream is no longer responsible for cleaning up the storage. You took over that responsibility when you asked for the char * with str( ). We can clean the storage in two ways: Using the delete operator as shown below:
ostrstream s ;
char *p ;
p = s.str( ) ;
delete p ;
By unfreezing the ostrstream. You do this by calling freeze( ), with an argument 1. During freezing it is called with the default argument of 0