Docstoc

C C INLINE Functions When a function is

Document Sample
C C INLINE Functions When a function is Powered By Docstoc
					C++
INLINE Functions
When a function is declared inline, the function is expanded at the calling block. The function is
not treated as a separate unit like other normal functions.

   But a compiler is free to decide, if a function qualifies to be an inline function. If the inline
function is found to have larger chunk of code, it will not be treated as an inline function, but as
like other normal functions.

  Inline functions are treated like macro definitions by the C++ compiler. They are declared with
the keyword inline as follows.

 //Declaration for C++ Tutorial inline sample:
  int add(int x,int y);

  //Definition for C++ Tutorial inline sample:
   inline int add(int x,int y)
   {
      return x+y;
   }
   In fact, the keyword inline is not necessary. If the function is defined with its body directly and
the function has a smaller block of code, it will be automatically treated as inline by the compiler.

  As implied, inline functions are meant to be used if there is a need to repetitively execute a
small block of code, which is smaller. When such functions are treated inline, it might result in a
significant performance difference.



Static Functions
Static data types can be accessed without instantiation of the class in C++. This is applicable for
static functions also.
  The differences between a static member function and non-static member functions are as
follows.

       A static member function can access only static member data, static member functions
        and data and functions outside the class. A non-static member function can access all of
        the above including the static data member.
       A static member function can be called, even when a class is not instantiated, a non-
        static member function can be called only after instantiating the class as an object.
       A static member function cannot be declared virtual, whereas a non-static member
        functions can be declared as virtual
       A static member function cannot have access to the 'this' pointer of the class.

The static member functions are not used very frequently in programs. But nevertheless, they
become useful whenever we need to have functions which are accessible even when the class is
not instantiated

this pointer
The this pointer is used as a pointer to the class object instance by the member function. The
address of the class instance is passed as an implicit parameter to the member functions. The
sample below, in this c++ Tutorial shows how to use it. It is a common knowledge that C++ keeps
only one copy of each member function and the data members are allocated memory for all of
their instances. This kind of various instances of data are maintained using this pointer. Look at
the sample below, in this c++ Tutorial.

C++ Tutorial - important notes on this pointer:

       this pointer stores the address of the class instance, to enable pointer access of the
        members to the member functions of the class.
       this pointer is not counted for calculating the size of the object.
       this pointers are not accessible for static member functions.
       this pointers are not modifiable.

 Look at the following example to understand how to use the 'this' pointer explained in this C++
Tutorial.

  class this_pointer_example // class for explaining C++ tutorial
  {
      int data1;
   public:
      //Function using this pointer for C++ Tutorial
      int getdata()
      {
         return this->data1;
      }
    //Function without using this pointer
    void setdata(int newval)
    {
        data1 = newval;
    }
 };
   Thus, a member function can gain the access of data member by either using this pointer or
not.


Friend
Any data which is declared private inside a class is not accessible from outside the class. A
function which is not a member or an external class can never access such private data. But
there may be some cases, where a programmer will need access to the private data from non-
member functions and external classes. C++ offers some exceptions in such cases.

 A class can allow non-member functions and other classes to access its own private data, by
making them as friends. This part of C++ tutorial essentially gives two important points.

       Once a non-member function is declared as a friend, it can access the private data of the
        class
       similarly when a class is declared as a friend, the friend class can have access to the
        private data of the class which made this a friend

 Let's see a sample in this C++ tutorial for each of the above cases.
C++ Tutorial - Friend function sample:

  #include <iostream.h>
  //Declaration of the function to be made as friend for the C++ Tutorial sample
  int AddToFriend(int x);
  class CPP_Tutorial
  {
     int private_data;
     friend int AddToFriend(int x);
  public:
     CPP_Tutorial()
    {
        private_data = 5;
     }
  };
  int AddToFriend(int x)
  {
     CPP_Tutorial var1;
     return var1.private_data + x;
  }
  int main()
  {
     cout << "Added Result for this C++ tutorial: "<< AddToFriend(4)<<endl;
  }

  The output of the above C++ Tutorial sample will be
   Added Result for this C++ tutorial: 9

C++ tutorial - friend class:

  Declaration of a friend class is also similar. Only thing is a class definition is slightly different.

C++ Tutorial - Friend function:

  #include < iostream.h >
  class CPP_Tutorial
  {
     int private_data;
     friend class friendclass;
  public:
     CPP_Tutorial()
     {
        private_data = 5;
    }
  };
  class friendclass
  {
  public:
     int subtractfrom(int x)
     {
        CPP_Tutorial var2;
        return var2.private_data - x;
     }
  };
  int main()
  {
      friendclass var3;
      cout << "Added Result for this C++ tutorial: "<< var3.subtractfrom(2)<
  }

 The output of the above C++ Tutorial sample will be
   Subtracted Result for this C++ tutorial: 3

  This is a good way out given by C++ to avoid restrictions on private variables. But this should
be used with caution though. If all the functions and classes are declared as friends, then the
concept of encapsulation and data security will go for a toss.

 That is why the concept of friend functions and classes should be used with proper judgment.

Inheritance
Creating or deriving a new class using another class as a base is called inheritance in C++. The
new class created is called a Derived class and the old class used as a base is called a Base
class in C++ inheritance terminology.

  The derived class will inherit all the features of the base class in C++ inheritance. The derived
class can also add its own features, data etc., It can also override some of the features
(functions) of the base class, if the function is declared as virtual in base class.

  C++ inheritance is very similar to a parent-child relationship. When a class is inherited the entire
functions and data member are inherited, although not all of them will be accessible by the
member functions of the derived class. But there are some exceptions to it too.

Some of the exceptions to be noted in C++ inheritance are as follows.

         The constructor and destructor of a base class are not inherited
         the assignment operator is not inherited
         the friend functions and friend classes of the base class are also not inherited.

  There are some points to be remembered about C++ inheritance. The protected and public
variables or members of the base class are all accessible in the derived class. But a private
member variable not accessible by a derived class.

  It is a well known fact that the private and protected members are not accessible outside the
class. But a derived class is given access to protected members of the base class.

  Let us see a piece of sample code for C++ inheritance. The sample code considers a class
named vehicle with two properties to it, namely color and the number of wheels. A vehicle is a
generic term and it can later be extended to any moving vehicles like car, bike, bus etc.

  Class vehicle //Sample base class for c++ inheritance tutorial
  {
   protected:
     char color name [20];
     int number_of_wheels;
   public:
     vehicle ();
     ~vehicle ();
     void start ();
     void stop ();
     void run ();
   };

   Class Car: public vehicle //Sample derived class for C++ inheritance tutorial
   {
     protected:
       char type_of_fuel;
     public:
       Car ();
   };

  The derived class Car will have access to the protected members of the base class. It can also
use the functions start, stop and run provided the functionalities remain the same.

 In case the derived class needs some different functionalities for the same functions start, stop
and run, then the base class should implement the concept of virtual functions.




C++ virtual function is a member function of a class, whose functionality can be over-ridden in its
derived classes. The whole function body can be replaced with a new set of implementation in the
derived class. The concept of c++ virtual functions is different from C++ Function overloading.

C++ Virtual Function - Properties:

 C++ virtual function is,

       A member function of a class
       Declared with virtual keyword
       Usually has a different functionality in the derived class
       A function call is resolved at run-time

  The difference between a non-virtual c++ member function and a virtual member function is, the
non-virtual member functions are resolved at compile time. This mechanism is called static
binding. Where as the c++ virtual member functions are resolved during run-time. This
mechanism is known as dynamic binding.

C++ Virtual Function - Reasons:

  The most prominent reason why a C++ virtual function will be used is to have a different
functionality in the derived class.

  For example a Create function in a class Window may have to create a window with white
background. But a class called Command Button derived or inherited from Window, may have to
use a gray background and write a caption on the center. The Create function for Command
Button now should have a functionality different from the one at the class called Window.
C++ Virtual function - Example:

 This article assumes a base class named Window with a virtual member function named
Create. The derived class name will be CommandButton, with our over ridden function Create.

   Class Window // Base class for C++ virtual function example
   {
     public:
       virtual void Create() // virtual function for C++ virtual function example
       {
           cout <<"Base class Window"<<endl;
       }
   };

   class CommandButton : public Window
   {
     public:
       void Create()
       {
         cout<<"Derived class Command Button - Overridden C++ virtual function"<<endl;
       }
   };

   void main()
   {
     Window *x, *y;

       x = new Window();
       x->Create();

       y = new CommandButton();
       y->Create();
   }

 The output of the above program will be,
         Base class Window
         Derived class Command Button

  If the function had not been declared virtual, then the base class function would have been
called all the times. Because, the function address would have been statically bound during
compile time. But now, as the function is declared virtual it is a candidate for run-time linking and
the derived class function is being invoked.

C++ Virtual function - Call Mechanism:

  Whenever a program has a C++ virtual function declared, a v-table is constructed for the class.
The v-table consists of addresses to the virtual functions for classes and pointers to the functions
from each of the objects of the derived class. Whenever there is a function call made to the c++
virtual function, the v-table is used to resolve to the function address. This is how the Dynamic
binding happens during a virtual function call.
Abstract classes (C++ only)
An abstract class is a class that is designed to be specifically used as a base class. An
abstract class contains at least one pure virtual function. You declare a pure virtual
function by using a pure specifier (= 0) in the declaration of a virtual member function in
the class declaration.

The following is an example of an abstract class:

class AB {
public:
   virtual void f() = 0;
};

Function AB::f is a pure virtual function. A function declaration cannot have both a pure
specifier and a definition. For example, the compiler will not allow the following:

struct A {
   virtual void g() { } = 0;
};

You cannot use an abstract class as a parameter type, a function return type, or the type of
an explicit conversion, nor can you declare an object of an abstract class. You can,
however, declare pointers and references to an abstract class. The following example
demonstrates this:

struct A {
   virtual void f() = 0;
};

struct B : A {
   virtual void f() { }
};

// Error:
// Class A is an abstract class
// A g();

//   Error:
//   Class A is an abstract class
//   void h(A);
A&   i(A&);

int main() {
// Error:
// Class A is an abstract class
//   A a;

   A* pa;
   B b;

// Error:
// Class A is an abstract class
//   static_cast<A>(b);
}

Class A is an abstract class. The compiler would not allow the function declarations A
g() or void h(A), declaration of object a, nor the static cast of b to type A.

Virtual member functions are inherited. A class derived from an abstract base class will
also be abstract unless you override each pure virtual function in the derived class.

For example:

class AB {
public:
   virtual void f() = 0;
};

class D2 : public AB {
   void g();
};

int main() {
  D2 d;
}

The compiler will not allow the declaration of object d because D2 is an abstract class; it
inherited the pure virtual function f()from AB. The compiler will allow the declaration of
object d if you define function D2::g().

Note that you can derive an abstract class from a nonabstract class, and you can override
a non-pure virtual function with a pure virtual function.

You can call member functions from a constructor or destructor of an abstract class.
However, the results of calling (directly or indirectly) a pure virtual function from its
constructor are undefined. The following example demonstrates this:

struct A {
   A() {
     direct();
     indirect();
   }
   virtual void direct() = 0;
   virtual void indirect() { direct(); }
};
The default constructor of A calls the pure virtual function direct() both directly and
indirectly (through indirect()).

The compiler issues a warning for the direct call to the pure virtual function, but not for
the indirect call.




Virtual functions (C++ only)
By default, C++ matches a function call with the correct function definition at compile
time. This is called static binding. You can specify that the compiler match a function
call with the correct function definition at run time; this is called dynamic binding. You
declare a function with the keyword virtual if you want the compiler to use dynamic
binding for that specific function.

The following examples demonstrate the differences between static and dynamic binding.
The first example demonstrates static binding:

#include <iostream>
using namespace std;

struct A {
   void f() { cout << "Class A" << endl; }
};

struct B: A {
   void f() { cout << "Class B" << endl; }
};

void g(A& arg) {
   arg.f();
}

int main()
{
   B x;
   g(x);
}

The following is the output of the above example:

Class A

When function g() is called, function A::f() is called, although the argument refers to
an object of type B. At compile time, the compiler knows only that the argument of
function g() will be a reference to an object derived from A; it cannot determine whether
the argument will be a reference to an object of type A or type B. However, this can be
determined at run time. The following example is the same as the previous example,
except that A::f() is declared with the virtual keyword:

#include <iostream>
using namespace std;

Struct A {
   Virtual void f () {cout << "Class A" << endl ;}
};

Struct B: A {
   Void f () {cout << "Class B" << endl;}
};

Void g (A& arg) {
   arg.f ();
}

int main () {
   B x;
   G(x);
}

The following is the output of the above example:

Class B

The virtual keyword indicates to the compiler that it should choose the appropriate
definition of f() not by the type of reference, but by the type of object that the reference
refers to.

Therefore, a virtual function is a member function you may redefine for other derived
classes, and can ensure that the compiler will call the redefined virtual function for an
object of the corresponding derived class, even if you call that function with a pointer or
reference to a base class of the object.

A class that declares or inherits a virtual function is called a polymorphic class.

You redefine a virtual member function, like any member function, in any derived class.
Suppose you declare a virtual function named f in a class A, and you derive directly or
indirectly from A a class named B. If you declare a function named f in class B with the
same name and same parameter list as A::f, then B::f is also virtual (regardless whether
or not you declare B::f with the virtual keyword) and it overrides A::f. However, if
the parameter lists of A::f and B::f are different, A::f and B::f are considered
different, B::f does not override A::f, and B::f is not virtual (unless you have declared
it with the virtual keyword). Instead B::f hides A::f. The following example
demonstrates this:

#include <iostream>
Using namespace std;
Struct A {
   Virtual void f () {cout << "Class A" << endl ;}
};

Struct B: A {
   Void f (int) {cout << "Class B" << endl ;}
};

Struct C: B {
   Void f () {cout << "Class C" << endl ;}
};

int main() {
   B b; C c;
   A* pa1 = &b;
   A* pa2 = &c;
//   b.f();
   pa1->f ();
   pa2->f ();
}

The following is the output of the above example:

Class A
Class C

The function B::f is not virtual. It hides A::f. Thus the compiler will not allow the
function call b.f (). The function C::f is virtual; it overrides A::f even though A::f is
not visible in C.

If you declare a base class destructor as virtual, a derived class destructor will override
that base class destructor, even though destructors are not inherited.

The return type of an overriding virtual function may differ from the return type of the
overridden virtual function. This overriding function would then be called a covariant
virtual function. Suppose that B::f overrides the virtual function A::f. The return types
of A::f and B::f may differ if all the following conditions are met:

      The function B::f returns a reference or pointer to a class of type T, and A::f
       returns a pointer or a reference to an unambiguous direct or indirect base class of
       T.
      The const or volatile qualification of the pointer or reference returned by B::f has
       the same or less const or volatile qualification of the pointer or reference returned
       by A::f.
      The return type of B::f must be complete at the point of declaration of B::f, or it
       can be of type B.

The following example demonstrates this:
#include <iostream>
using namespace std;

struct A { };

class B : private A {
   friend class D;
   friend class F;
};

A global_A;
B global_B;

struct C {
   virtual A* f() {
      cout << "A* C::f()" << endl;
      return &global_A;
   }
};

struct D : C {
   B* f() {
      cout << "B* D::f()" << endl;
      return &global_B;
   }
};

struct E;

struct F : C {

//     Error:
//     E is incomplete
//     E* f();
};

struct G : C {

//     Error:
//     A is an inaccessible base class of B
//     B* f();
};

int main() {
   D d;
   C* cp = &d;
   D* dp = &d;

     A* ap = cp->f();
     B* bp = dp->f();
};

The following is the output of the above example:

B* D::f()
B* D::f()
The statement A* ap = cp->f() calls D::f() and converts the pointer returned to type
A*. The statement B* bp = dp->f() calls D::f() as well but does not convert the
pointer returned; the type returned is B*. The compiler would not allow the declaration of
the virtual function F::f() because E is not a complete class. The compiler would not
allow the declaration of the virtual function G::f() because class A is not an accessible
base class of B (unlike friend classes D and F, the definition of B does not give access to
its members for class G).

A virtual function cannot be global or static because, by definition, a virtual function is a
member function of a base class and relies on a specific object to determine which
implementation of the function is called. You can declare a virtual function to be a friend
of another class.

If a function is declared virtual in its base class, you can still access it directly using the
scope resolution (::) operator. In this case, the virtual function call mechanism is
suppressed and the function implementation defined in the base class is used. In addition,
if you do not override a virtual member function in a derived class, a call to that function
uses the function implementation defined in the base class.

A virtual function must be one of the following:

       Defined
       Declared pure
       Defined and declared pure

A base class containing one or more pure virtual member functions is called an abstract
class.



Virtual destructors
Ask any programmer, he'll immediately reply saying "A destructor is a member function of a class,
which gets called when the object goes out of scope". This means all clean ups and final steps of
class destruction are to be done in destructor. A virtual function is something which helps a
derived class in overriding the implementation of a functionality of a base class.

A destructor is called whenever an object is deleted, there are some cases when users
code doesn?t know which destructor should be called. If a base class pointer is pointing
to derived class objects. when the object dies only the base class destructor is called. This
could be a serious error, especially if the derived destructor is supposed to release some
resources. Virtual destructors are extremely valuable when some derived classes have
some specified cleanup code. If any code anywhere deletes an derived class object via a
base class pointer, then the base class?s destructor needs to be virtual.
The order of execution of destructor in an inherited class during a clean up is like this.
1. Derived class destructor
2. Base class destructor

A difference between a destructor (of course also the constructor) and other member functions is
that, if a regular member function has a body at the derived class, only the version at Derived
class gets executed. Whereas in case of destructors, both derived as well as base class versions
get executed.

Now turning our attention to why a destructor has to be virtual, the reason is that we,
programmers are very smart. We'll do days and nights of work to inherit and extend the
functionality of an existing class which is being used, and say that we don't want to change the
implementation/interface just for the sake of a new entrant. Let me explain this with an example.



#include <iostream.h>
class Base
{
      public:
        Base(){ cout<<"Constructor: Base"<<endl;}
        ~Base(){ cout<<"Destructor : Base"<<endl;}
};
class Derived: public Base
{
    //Doing a lot of jobs by extending the functionality
      public:
        Derived(){ cout<<"Constructor: Derived"<<endl;}
        ~Derived(){ cout<<"Destructor : Derived"<<endl;}
> };
void main()
{
       Base *Var = new Derived();
       delete Var;
}

Try executing this code, you'll see the difference. To our observation, the constructors are getting
called in the proper order. But to the dread of a programmer of a large project, the destructor of
the derived class was not called at all.

This is where the virtual mechanism comes into our rescue. By making the Base class Destructor
virtual, both the destructors will be called in order. The following is the corrected sample.

#include <iostream.h>
class Base
{
     public:
       Base(){ cout<<"Constructor: Base"<<endl;}
       virtual ~Base(){ cout<<"Destructor : Base"<<endl;}
};
class Derived: public Base
{
   //Doing a lot of jobs by extending the functionality
     public:
        Derived(){ cout<<"Constructor: Derived"<<endl;}
      ~Derived(){ cout<<"Destructor : Derived"<<endl;}
};
void main()
{
     Base *Var = new Derived();
     delete Var;
}

Note:
There is one more point to be noted regarding virtual destructor. We can't declare pure virtual
destructor. Even if a virtual destructor is declared as pure, it will have to implement an empty
body (at least) for the destructor.




                                 Virtual Functions
This article discusses Virtual Functions in detail with some lucid code examples.


The concept of a Virtual Destructor is also covered.

What is a Virtual Function?

A virtual function is a member function of a class, whose functionality can be over-
ridden in its derived classes. It is one that is declared as virtual in the base class using the
virtual keyword. The virtual nature is inherited in the subsequent derived classes and the
virtual keyword need not be re-stated there. The whole function body can be replaced
with a new set of implementation in the derived class.

What is Binding?

Binding refers to the act of associating an object or a class with its member. If we can call
a method fn() on an object o of a class c, we say that the object o is binded with the
method fn(). This happens at compile time and is known as static or compile - time
binding. The calls to the virtual member functions are resolved during run-time. This
mechanism is known as dynamic binding. The most prominent reason why a virtual
function will be used is to have a different functionality in the derived class. The
difference between a non-virtual member function and a virtual member function is, the
non-virtual member functions are resolved at compile time.

How does a Virtual Function work?

Whenever a program has a virtual function declared, a v - table is constructed for the
class. The v-table consists of addresses to the virtual functions for classes that contain
one or more virtual functions. The object of the class containing the virtual function
contains a virtual pointer that points to the base address of the virtual table in memory.
Whenever there is a virtual function call, the v-table is used to resolve to the function
address. An object of the class that contains one or more virtual functions contains a
virtual pointer called the vptr at the very beginning of the object in the memory. Hence
the size of the object in this case increases by the size of the pointer. This vptr contains
the base address of the virtual table in memory. Note that virtual tables are class specific,
i.e., there is only one virtual table for a class irrespective of the number of virtual
functions it contains. This virtual table in turn contains the base addresses of one or more
virtual functions of the class. At the time when a virtual function is called on an object,
the vptr of that object provides the base address of the virtual table for that class in
memory. This table is used to resolve the function call as it contains the addresses of all
the virtual functions of that class. This is how dynamic binding is resolved during a
virtual function call.

The following code shows how we can write a virtual function in C++ and then use the
same to achieve dynamic or runtime polymorphism.

#include <iostream.h>
class base
{
public:
virtual void display()
{
  cout<<”\nBase”;
}
};
class derived : public base
{
  public:
  void display()
  {
    cout<<”\nDerived”;
  }
};

void main()
{
  base *ptr = new derived();
  ptr->display();
}

In the above example, the pointer is of type base but it points to the derived class object.
The method display () is virtual in nature. Hence in order to resolve the virtual method
call, the context of the pointer is considered, i.e., the display method of the derived class
is called and not that of the base. If the method was non virtual in nature, the display ()
method of the base class would have been called.
Virtual Constructors and Destructors

A constructor cannot be virtual because at the time when the constructor is invoked the
virtual table would not be available in the memory. Hence we cannot have a virtual
constructor.

A virtual destructor is one that is declared as virtual in the base class and is used to ensure
that destructors are called in the proper order. It is to be remembered that destructors are
called in the reverse order of inheritance. If a base class pointer points to a derived class
object and we some time later use the delete operator to delete the object, then the
derived class destructor is not called. Refer to the code that follows:

#include <iostream.h>
class base
{
   public:
   ~base()
  {

 }
};

class derived : public base
{
  public:
  ~derived()
  {

  }
};

void main()
{

    base *ptr = new derived();
    // some code
    delete ptr;
}

In this case the type of the pointer would be considered. Hence as the pointer is of type
base, the base class destructor would be called but the derived class destructor would not
be called at all. The result is memory leak. In order to avoid this, we have to make the
destructor virtual in the base class. This is shown in the example below:

#include <iostream.h>
class base
{
public:
virtual ~base()
{

}
};

class derived : public base
{
  public:
  ~derived()
  {

    }

};

void main()
{

    base *ptr = new derived();
    // some code
    delete ptr;
}

Conclusion:

Virtual methods should be used judiciously as they are slow due to the overhead involved
in searching the virtual table. They also increase the size of an object of a class by the
size of a pointer. The size of a pointer depends on the size of an integer. Note that in DOS
based systems the size of a pointer is 2 bytes whereas in UNIX based systems it is 4
bytes.



COPY CONSTRUCTOR

When copies of objects are made

A copy constructor is called whenever a new variable is created from an
object. This happens in the following cases (but not in assignment).

               A variable is declared which is initialized from another object, e.g.,
                Person q("Mickey"); // constructor is used to build q.
           Person r(p);          // copy constructor is used to build r.
           Person p = q;         // copy constructor is used to initialize in
            declaration.
             p = q;                // Assignment operator, no constructor or
             copy constructor.
          A value parameter is initialized from its corresponding argument.

             f(p);                 // copy constructor initializes formal
             value parameter.
          An object is returned by a function.

C++ calls a copy constructor to make a copy of an object in each of the
above cases. If there is no copy constructor defined for the class, C++ uses
the default copy constructor which copies each field, i.e., makes a shallow
copy.

Don't write a copy constructor if shallow copies are ok

If the object has no pointers to dynamically allocated memory, a shallow
copy is probably sufficient. Therefore the default copy constructor, default
assignment operator, and default destructor are ok and you don't need to
write your own.

If you need a copy constructor, you also need a destructor and
operator=

If you need a copy constructor, it's because you need something like a deep
copy, or some other management of resources. Thus it is almost certain that
you will need a destructor and override the assignment operator.

Copy constructor syntax

The copy constructor takes a reference to a const parameter. It is const to
guarantee that the copy constructor doesn't change it, and it is a reference
because a value parameter would require making a copy, which would invoke
the copy constructor, which would make a copy of its parameter, which
would invoke the copy constructor, which ...

Here is an example of a copy constructor for the Point class, which doesn't
really need one because the default copy constructor's action of copying
fields would work fine, but it shows how it works.

  //=== file Point.h =============================================
  class Point {
           public:
               . . .
             Point(const Point& p);             // copy constructor
             . . .
  //=== file Point.cpp ==========================================
  . . .
  Point::Point(const Point& p) {
         x = p.x;
         y = p.y;
  }
         . . .
  //=== file my_program.cpp ====================================
  . . .
  Point p;                    // calls default constructor
  Point s = p;                // calls copy constructor.
  p = s;                      // assignment, not copy constructor.

Difference between copy constructor and assignment

A copy constructor is used to initialize a newly declared variable from an
existing variable. This makes a deep copy like assignment, but it is
somewhat simpler:

      1. There is no need to test to see if it is being initialized from itself.
      2. There is no need to clean up (eg, delete) an existing value (there is
         none).
      3. A reference to itself is not returned.


Overriding in Object Oriented Programming - an article by Birendra
Keshari
   Overriding is an important concept in Object Oriented Technology. In today's world you can't
live without overriding. For example in most of the API's used for building windows based
application you always need to override some parent window. Like in Java you may override
methods and data of class Frame, in C++ CMainWnd, in QT Form etc. In many of your
applications that you build using Inheritance you need to override some members of the parent
class.

  Let's understand inheritance by an analogous example. Let C be the son of F. There can be
many characteristics that C inherit from his/her father F. Like may be he also loves listening to
music and so does C, F is genius and so is C, F writes poems like C does. These all are inherited
characteristics. But there can be situation like C writes romantic poems and his/her father used to
write tragic poems. Here, C has overridden his/her father's characteristics of writing a poem. It
was inherited from his/her father but he/she does it differently. The concept of overriding is same
in Object Oriented Programming Languages.
  For overriding, there must be inheritance. Once you inherit, you can then override data
member of methods of the parent class. In C++ ":" is used to tell C++ compiler that you want to
inherit something. For example "Class MangoTree : public Tree " means class MangoTree is
inheriting class Tree.
The keyword public adds the information that only the public members are inherited. Once class
MangoTree inherits class Tree, all the public members of class Tree are accessible from class
MangoTree. Like is there is a data member "height" defined in class "Tree" you can directly use
this variable in any method of class "MangoTree". Similar is the case with methods. But,
sometimes you would like to change the implementation of some of the methods of the parent
class. Like though there was a method called, "getFruitName()", you would write another method
of the same name and parameter in class "MangoTree". The method "getFruitName()" of parent
class is not visible in child class "MangoTree" now. It has its own now. It has overridden the
method of its parent. Similarly, it can also override the data member of its parent. This is what
known as overriding, a popular technique in object oriented paradigm.

 The following code shows an example of inheritance while building a MFC application.




    class Application: public CWinApp
   {
      BOOL InitInstance ();
   }




  In the above code fragment, class Application inherits class CWinApp. It is the case for every
application that are build using MFC. Class Application also inherits the method “InitInstance of
class CWinApp. But, it overrides it. So, it can have its own new implementation. This method can
be called from the CWinApp or some other class collaborated with CWinApp, thus, there is no
need of knowing in advance what will be inside this method. The user can do the things inside
this method in
his/her own way.




Dynamic memory allocation in C++
So you have just finished your program and you would like to see it at work. Usually you press a
combination of keys to compile and run it. But what actually happens when you press those
keys? The compilation process translates your code from C++ to machine language, which is the
only language computers "understand". Then your application is given a certain amount of
memory to use, which is divided into three segments as follows :

    o   Code Segment, in which all the application code is stored
    o   Data Segment, that holds the global data
    o   Stack Segment, used as a container for local variables and other temporary information.

In addition to these, the operating system also provides an extra amount of memory called Heap.

Now let us recall what a C++ variable consisted of:
      o   name, an identifier to recognize the variable
      o   type, the set of values it may take
      o   scope, the area of code in which it is visible
      o   address, the address at which the variable is allocated
      o   size, the amount of memory used to store its contents.

Consider the following sequence of code :

     void cookie() {
        int integer_X;
        ...
     }

Let us try to figure out what are the attributes of the variable declared inside this function.

      o   name : integer_X
      o   type : int
      o   scope : local, only visible within the cookie function
      o   address : a certain address in the stack segment, where the variable is allocated
      o   size : 32 bits (depending on the compiler)

What is a pointer then? We all heard about it, it is the variable declared with a star in front of it...
but let us try and put some order in what we know by enumerating its exact attributes:

      o   name : an arbitrary identifier
      o   type : integer address
      o   scope : local or global (depending on the situation)
      o   address : the address in the data segment (if it is global) or stack segment (if it is local)
      o   size : 32 bits (16 bits for segment + 16 bits for offset of the address it points to)

A dynamic variable is a variable that is stored in the heap, outside the data and stack segments,
that may change size during runtime or may even disappear for good. In fact if we do not allocate
a certain amount of memory to store its contents, it will never exist.

For example consider the next declaration:

double *dp;

This tells the compiler we have a pointer dp that may hold the starting address of a dynamic
variable of type double. However, the dynamic variable does not exist yet - to create it we must
use the new operator like this:

dp = new double;

Remember one thing - dynamic variables are never initialized by the compiler. Therefore it is
good practice to first assign them a value, or your calculations may not come out right. There are
two ways of doing this:

dp = new double;
*dp = a;

or
dp = new double (a);

where a is the initial value. I personally recommend the second version as it is more suggestive
and also more compact.

Consider this line of code:

double *dp = new double (3.1415);

The diagram below shows the possible connection between dp and the dynamic variable
associated with it, after the previous line is executed.




Now consider you have decided to erase the dynamic variable for good from the heap. Use the
delete operator to achieve this:

delete dp;

Notice that while we have freed 8 bytes of memory - which is sizeof (double) - the dp
pointer was not erased. It still exists in the data or stack segment of the application and we may
use it to initialize another dynamic variable.

C++ also provides the possibility to allocate an entire array in the heap, keeping a pointer to its
first element. Again we use the new operator but mention the size of the array in square brackets:

  int *table;
  table = new int[100];

This will allocate 100 * sizeof (int) = 100 * 4 = 400 bytes of memory and assign the
starting address of the memory block to the table pointer.

Arrays allocated in the heap are similar to those allocated in the data or stack segments, so we
may access an arbitrary element using the indexing operator []. For example the next loop
initializes each element of the array to zero:

  for (int i = 0; i < 100; ++i)
      table[i] = 0;

Bad news is C++ does not provide any method of initializing heap arrays as you would an
ordinary dynamic variable, so we have to do it ourselves using a loop similar to the one above.
The following line will generate errors at compilation:

table = new int [100] (0);
To erase a heap-allocated array we will use the delete operator, but this time add a pair of
square brackets so that the compiler can differentiate it from an ordinary dynamic variable.

delete [] table;

All we have learned so far are means of replacing the old malloc() and free () functions in C
with their new and delete C++ analogues. The main reason is that they are better alternatives
to dynamic memory allocation and also have a more compact syntax. However C pointer
arithmetic’s and other pointer operations are also available in C++.




Memory corruption
Memory is said to be corrupted if we try one of the following:

    o   Free a dynamic variable that has already been freed

  char *str = new char[100];
  delete [] str;
  delete [] str;

    o   Free a dynamic variable that has not been yet allocated

  char *str;
  delete str;

    o   Assign a certain value to a dynamic variable that was never allocated

  char *str;
  strcpy(str, "error");

The previous three examples will most probably cause the application to crash. However the next
two "bugs" are harder to detect:

    o   Assign a certain value to a dynamic variable, after it has been freed (this may also affect
        other data stored in the heap)

  char *str = new char[100];
  delete [] str;
  char *test = new char[100];
  strcpy (str, "surprise!");
  cout << test;
  delete [] test;

    o   Access an element with an index out of range

  char *str = new char[30];
  str[40] = 'C';
Last but not least, remember it is good practice to test whether allocation was or was not
successful before proceeding with the code. The reason for this is that the operating system may
run out of heap at some point, or the memory may get too fragmented to allow another allocation.

  char *str = new char[512];
  if (str == NULL) {
     // unable to allocate block of memory!
  }

				
DOCUMENT INFO
Shared By:
Tags: Interview
Stats:
views:39
posted:2/18/2010
language:English
pages:25
Description: which contains the interview questions and answers and concepts.
sreekanth reddy sreekanth reddy Software Engineer englishmoviedl.blogspot.com
About i am peaceful and kind person