Welcomes U........

 

 HOME
 TUTORIALS
 THOUGHTS
 POETRY
 PROJECTS
 ABOUT-ME
 CONTACT
 FRIENDS
 ROBOTICS
 let's go 

 Good Questions In C++

!!Enjoy!!!

 

 

85.

How do I call a virtual function of a class using a pointer to a function ?

      Ans :

      #include <iostream.h>

      class Cvirtual

      {

      public :

      virtual float vfun( )

      {

      cout << "from vfun" << endl ;

      return 7.03f ;

      }

      } ;

      void main( )

      {

      Cvirtual obj ;

      int **p = ( int ** ) &obj ;

      float ( *pf1 ) ( ) ;

      pf1 = ( float ( * ) ( ) ) **p ;

      float f = ( *pf1 ) ( ) ;

      cout << "return val = " << f << endl ;

      }

      

In the above program class Cvirtual consists of a virtual function vfun(). In variable p we have stored the address of an object of class Cvirtual. While doing so, we have type casted the address of obj to int **, because obj holds a hidden data member called vptr, which in turn holds the address of virtual function vfun( ). In pf1, a pointer to a function, we are collecting the address of the virtual function vfun( ). Thus the value returned by vfun( ) would then get collected in f.

-------------------------------------------------------------------------------------------------

 

 

86.

Why an overloaded new operator defined in a class is static?

      

Ans: An overloaded new function is by default static even if it is not  declared so. This is because non-static member functions can be called  through  an object only. But when an overloaded new operator function gets called the object doesn't stand created. Since new operator function  itself is responsible for creating the object. Hence to be able to call a function without an object, the function must be static.

-------------------------------------------------------------------------------------------------

87.

What is a pure virtual destructor?

      

Ans: Like a pure virtual function we can also have a pure virtual destructor. If a base class contains a pure virtual destructor it becomes necessary for the derived classes to implement the destructor. An ordinary pure virtual function does not have a body but pure virtual destructor must have a body. This is because all the destructors in the hierarchy of inheritance are always called as a part of destruction.

-------------------------------------------------------------------------------------------------

88.

When we are required to find offset of an element within a structure? or, how do we call the function of an outer class from a function in the inner class? (The inner class is nested in the outer class)

      Ans:

      #include  <iostream.h> 

      class outer  

      { 

      int i ;  

      float f ; 

      public : 

      class inner  

      { 

      public : 

      infunc( )  

      { 

      outer *pout ;  

      pout = (outer*) this - ( size_t ) &( ( ( outer* ) 0 ) -> in ) ;  

      pout -> outfunc( ) ; 

      } 

      } ;  

      inner in ;  

      outfunc( )  

      { 

      cout << "in outer class's function" ; 

      } 

      } ;  

      void main( )  

      { 

      outer out ;  

      out.in.infunc( )  

      }

In the above example we are calling outer::outfunc( ) from inner::infunc(). To call outfunc( ) we need a pointer to the outer class. To get the pointer we have subtracted offset of the inner class's object (base       address of outer class's object - address of inner class's object) from address of inner class's object.

-------------------------------------------------------------------------------------------------

89.

 

      void f ( float n, int i = 10 ) ;

      void f ( float a ) ;

      void main( )

      {

      f ( 12.6 ) ;

      }

      

      void f ( float n, int i )

      {

      

      }

      

      void f ( float n )

      {

      

      }

      

The above program results in an error (ambiguous call) since without the default argument the two functions have arguments that are matching in number, order and type.

-------------------------------------------------------------------------------------------------

90.

Some programs need to exercise precise control over the memory areas where data is placed. For example, suppose we wish to read the contents of the boot sector into a structure. For this the byte arrangement of the

structure elements must match the arrangement of various fields in the boot sector of the disk.

 

The #pragma pack directives offer a way to fulfill this requirement. The #pragma pack directive specifies packing alignment for structure and union members. The #pragma takes effect at the first structure or union       declaration after the #pragma is seen. Consider the following structure: 

      #pragma pack (1)

      struct emp

      {

      int a ;

      float s ;

      char ch ;

      } ;

      #pragma pack( )

Here, #pragma pack ( 1 ) lets each structure element to begin on a 1-byte boundary. Hence the size of the structure will be 9. (int - 4, float - 4, char - 1). If we use #pragma pack ( 2 ) each structure element can begin       on a 2-byte boundary. Hence the size of the structure will be 10. (int - 4, float - 4, char - 2).

-------------------------------------------------------------------------------------------------

91.

How to restrict a friend class's access to the private data members?

 

Ans: If we declare a class as a friend of our class the friend class can access the private data members of our class. However, if we want we can restrict this access to some selective functions of the class. Following program shows how to achieve this:

      

      #include <iostream.h>

      class X

      {

      public :

      void print ( class Z &z ) ;

      } ;

      class Z

      {

      private :

      int i ;

      public :

      Z ( int ii )

      {

      i = ii ;

      }

      friend X::print ( class Z &z ) ;

      } ;

      void X::print ( Z &z1 )

      {

      cout << z1.i ;

      }

      main( )

      {

      Z z ( 10 ) ;

      X x ;

      x.print ( 10 ) ;

      }

      

In the above program only the X::print( ) function can access the private data members of class Z.

-------------------------------------------------------------------------------------------------

92.

 

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.      

-------------------------------------------------------------------------------------------------

93.

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 <stdio.h>

      void f( )

      {

          printf ( "in f( )" ) ;

      }

      // In func.cpp

      #include <iostream.h>

      extern "C" void f( ) ;

      void main( )

      {

          f( ) ;

      }

      Ensure that both .c and .cpp files are in the same project.

    

-------------------------------------------------------------------------------------------------

 

94.

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.

-------------------------------------------------------------------------------------------------

95.

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.

-------------------------------------------------------------------------------------------------

 

 

96.

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 <iostream.h>

 

      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.

-------------------------------------------------------------------------------------------------

97.

 

      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 how to do this.

      class sample

      {

      private :

      int data ;

      public :

      void fun( ) const

      {

      ( const_cast <sample *> ( this ) ) -> data = 70 ; 

      }

      } ;

-------------------------------------------------------------------------------------------------

98.

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 <iostream.h>

 

      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.

     

-------------------------------------------------------------------------------------------------

99.

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

      }

-------------------------------------------------------------------------------------------------

100.

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.

-------------------------------------------------------------------------------------------------

101.

 

Why in a copy constructor an object is collected in a reference to object as shown below?

      #include <iostream.h>

      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.

-------------------------------------------------------------------------------------------------

102.

 

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.

-------------------------------------------------------------------------------------------------

103.

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.

-------------------------------------------------------------------------------------------------

 

                                                                      Thanks for your Visit.

 

   

For Any Query or Suggestion Mail ME  :   ([email protected])

Hosted by www.Geocities.ws

1