Const Functions in C++

The Const member functions are used to prevent modifications of class data members within it.Likewise,the const parameters are used to prevent modification of data collected by them.

class sample
{
     int i;
     public:
               int fun() const
               {
                      i=82;   //error
                      return i;
               }
               void fun1(const int &ii)
               {
                      ii=8;    //error
               }
};
void main()
{
      sample s;
      int p=9;
      p=s.fun();
      s.fun1(p);
}

Here fun() is a const member function.Hence ,compiler flashes an error when we try to modify the data member i.Similarly,the function fun1() cannot modify the value of ii as ii is declared as const.

Const Data in C++

Once the const data members are initialized they can not be changed.Hence the known constants such as value of PI etc.that never change should be declared as const.

How to Initialize a const data member:
class sample
{
     const int t;
     public:
              sample(int i):t(i);
              {
              }
};
void main()
{
      sample s(25);
}

Here, t is the const data member of the class sample.When an object s is created,25 is passed to the one-argument constructor.It gets collected in parameter i which is then assigned to t.It is necessary to initialize the const data member in the definition of the constructor as shown in the program.

RTTI

RTTI stands for Run Time Type Identification.In an inheritance hierarchy,using RTTI we can find the exact type of the object using a pointer or reference to the base class.

How to get the information about the object at run time?
There are two ways to get the information about the object at run time they are as follows:

  • Using typeid() operator
  • Using dynamic_cast operator
Example:

Class Sample
{
    //Code
};
void main()
{
     Sample s;
     cout<<typeid(s).name();
}

The operator typeid() takes an object s and returns a reference to a global const object of the type type_info,then function name() is called to get the name of the class of the object.To use the type_info objects reference we need to include the header file "typeinfo.h".

The dynamic_cast operator can also be used to get the information of the object at run time.

Operator Overloading in C++

Operator overloading means giving capability to the operator to work on different types of operands.The operators +,*, etc work on operands of type int,float,etc.we can overload these operators by giving them the  capability to work on user-defined data types.

For example,to add two structure variables of type data we can write the following code;

struct data
{
      int i;
      float f;
};
data c,a={1,2.5f},b={3,5.5f};
c = a+b;

instead of,
c.i=a.i+b.i;
c.f=a.f+b.f;

in a+b,the '+' operator is overloaded to add two structure variables.we would of course have to provide the overloaded operator + function to carry out the addition.

Explicit Constructor in C++

In C++ it is possible to declare constructors for a class, taking a single parameter, and use those constructors for doing type conversion. 

class A 
{ 
       public: 
              A(int); 
}; 
void main()
{
       A a1=37;
}

A declaration like:
       A a1 = 37; 
says to call the A(int) constructor to create an A object from the integer value. Such a constructor is called a "converting constructor".

However, this type of implicit conversion can be confusing, and there is a way of disabling it, using a new keyword "explicit" in the constructor declaration: 
class A 
        public: 
                explicit A(int); 
}; 
void f(A) { } 
void g() 
       A a1 = 37; // illegal 
       A a2 = A(47); // OK 
       A a3(57); // OK 
       a1 = 67; // illegal 
       f(77); // illegal 
}

Virtual Functions in C++

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.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 calledCommandButton derived or inherited from Window, may have to use a gray background and write a caption on the center. The Create function for CommandButton 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"; 

         }
};

class CommandButton : public Window
{
     public:
        void Create()
        {
         cout<<"Derived class Command Button";
        }
};

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.

Assignment Operator in C++

The assignment operator for a class is what allows you to use = to assign one instance to another.

The assignment operator is used to copy the values from one object to another already existing object
For example:
        MyClass c1, c2; 
        c1 = c2; // assigns c2 to c1

There are actually several different signatures that an
assignment operator can have:

(1) MyClass& operator=( const MyClass& rhs );
(2) MyClass& operator=( MyClass& rhs );
(3) MyClass& operator=( MyClass rhs );
(4) const MyClass& operator=( const MyClass& rhs );
(5) const MyClass& operator=( MyClass& rhs );
(6) const MyClass& operator=( MyClass rhs );
(7) MyClass operator=( const MyClass& rhs );
(8) MyClass operator=( MyClass& rhs );
(9) MyClass operator=( MyClass rhs );

First, you should understand that if you do not declare an assignment operator, the compiler gives you one implicitly. The implicit assignment operator does member-wise assignment of each data member from the source object.If you are having any dynamic memory allocation data,we have to provide assignment operator otherwise compiler will take care.

Friend Functions & Friend Class

Friend Functions:

A C++ friend functions are special functions which can access the private members of a class. They are considered to be a loophole in the Object Oriented Programming concepts, but logical use of them can make them useful in certain cases. For instance: when it is not possible to implement some function, without making private members accessible in them. This situation arises mostly in case of operator overloading.


Friend functions have the following properties:

1) Friend of the class can be member of some other class.
2) Friend of one class can be friend of another class or all the classes in one program, such a friend is known as GLOBAL FRIEND.
3) Friend can access the private or protected members of the class in which they are declared to be friend, but they can use the members for a specific object.
4) Friends are non-members hence do not get “this” pointer.
5) Friends, can be friend of more than one class, hence they can be used for message passing between the classes.
6) Friend can be declared anywhere (in public, protected or private section) in the class.

Friend Classes:

A class can also be declared to be the friend of some other class. When we create a friend class then all the member functions of the friend class also become the friend of the other class. This requires the condition that the friend becoming class must be first declared or defined (forward declaration).

Templates in C++

C++ templates are a powerful mechanism for code reuse, as they enable the programmer to write code that behaves the same for data of any type. 

Suppose you write a function printData:

void printData(int value)
{
        std::cout<<"The value is "<<value<<std::endl;
}

If you later decide you also want to print double values, or std::string values, then you have to overload the function:

void printData(double value)
{
        std::cout<<"The value is "<<value<<std::endl;
}
void printData(std::string value)
{
        std::cout<<"The value is "<<value<<std::endl;
}

The actual code written for the function is identical in each case; it is just the type of the variable value that changes, yet we have to duplicate the function for each distinct type. This is where templates come in - they enable the user to write the function once for any type of the variable value.

template<typename T>
void printData(T value)
{
        std::cout<<"The value is "<<value<<std::endl;
}


Templates are of two types:
  • Function Templates
  • Class Templates

Function Templates:

Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type.

Class Templates:

We also have the possibility to write class templates, so that a class can have members that use template parameters as types.

What is conversion operator??

class can have a public method for specific data type conversions.

for example:

class Boo
{
         double value;
         public:
                  Boo(int i ){}
                  operator double()
                  {
                          return value;
                  }
};

Boo BooObject;
double i = BooObject; // assigning object to variable i of type double. now conversion operator gets called to assign the value.

What is conversion constructor?

constructor with a single argument makes that constructor as conversion constructor and it can be used for type conversion.

for example:

class Boo
{
    public:
            Boo( int i );
};

Boo BooObject = 10 ; // assigning int 10 Boo object

What are storage qualifiers in C++ ?

  1. const
  2. volatile
  3. mutable 
Const keyword indicates that memory once initialized, should not be altered by a program.

volatile keyword indicates that the value in the memory location can be altered even though nothing in the program
code modifies the contents. for example if you have a pointer to hardware location that contains the time, where hardware changes the value of this pointer variable and not the program. The intent of this keyword to improve the optimization ability of the compiler.

mutable keyword indicates that particular member of a structure or class can be altered even if a particular structure variable, class, or class member function is constant.

struct data
{
        char name[80];
        mutable double salary;
}

const data MyStruct = { "Satish Shetty", 1000 }; //initlized by complier

strcpy ( MyStruct.name, "Shilpa Shetty"); // compiler error
MyStruct.salaray = 2000 ; // complier is happy allowed

Pure Virtual Function

A Pure Virtual Function is a Virtual function with no body.

Since pure virtual function has no body, the programmer must add the notation =0 for declaration of the pure virtual function in the base class.

class class_name //This denotes the base class of C++ virtual function


       public: 
               //This denotes the pure virtual  function in C++
               virtual void virtualfunctioname() = 0;

};

if the class is having at least one pure virtual functions,we can not create object for this class

C++ Tips

  • dynamic storage - refers to memory allocated and deallocated during program execution using the new operator and delete operator. 
  • dynamic_cast - a C++ keyword that specifies a style of cast used with run-time type information. Using dynamic_cast one can obtain a pointer to an object of a derived class given a pointer of a base class type. If the object pointed to is not of the specified derived class, dynamic_cast will return 0. 
  • explicit - a C++ keyword used in the declaration of constructors to indicate that conversion of an initializer should not take place 
  • garbage collection - a way of automatically managing dynamic storage such that explicit cleanup of storage is not required. C++ does not have garbage collection. 
  • NULL - a special constant value that represents a null pointer. 
  • null pointer - a pointer value that evaluates to zero. 
  • object - has several meanings. In C++, often refers to an instance of a class. Also more loosely refers to any named declaration of a variable or other entity that involves storage 
  • OOA / OOD - acronym for object-oriented analysis and object-oriented design, processes of analyzing and designing object-oriented software 
  • pragma - a preprocessor directive used to affect compiler behavior in an implementation-defined way.

Abstract class

Abstract class - a class that can only be used as a base class for some other class. A class is abstract if it has at least one pure virtual function.

Object can’t be created in Abstract class.

Class data

{      
      public: 
             virtual void display()=0; // pure virtual fn declaration 
}; 
Class item : public data
     public:      
            void display() // pure virtual fn definition 
            {
                   cout<<”Pure Virtual fn calling”;
            }
};

If memory is allocated dynamically using new then can we expand the allocated memory using realloc( )?

Yes, we can! This can be explained with the help of following example:

#include <iostream.h>
#include <malloc.h> 
void main( )

       int *p = new int[5] ; 
       p[1] = 3 ; 
       p = ( int * ) realloc ( p, sizeof ( int ) * 5 ) ; 
       cout << p[1] ; 


The realloc( ) function expands the existing allocated memory if it finds enough contiguous memory locations that are required. If enough contiguous memory blocks are not available then the new memory block is allocated. The existing data is copied and the original memory block is freed.

How to allocate memory for a multidimensional array dynamically?

Many times we need to allocate memory for a multidimensional array dynamically. Because of complexity of pointers many find this difficult. Following program allocates memory for a 3 x 3 array dynamically, copies contents of a 3 x 3 array in it and prints the contents using the pointer.

#include <iostream.h>

int a[ ][3] = { 1, 2, 3, 
                     4, 5, 6, 
                     7, 8, 9 
                  } ; 

void main( )

{       int **p ; 
      p = new int *[3] ; 
      for ( int i = 0 ; i < 3 ; i++ ) 
               p[i] = new int[3] ; 
      for ( i = 0 ; i < 3 ; i++ ) 
         for ( int j = 0 ; j < 3 ; j++ ) 
              p[i][j] = a[i][j] ; 
      for ( i = 0 ; i < 3 ; i++ )
      { 
         for ( j = 0 ; j < 3 ; j++ ) 
         cout << p[i][j] ; 
         cout << "\n" ; 
      } 
}

Virtual Destructor in C++

• Pointer is of type Base class and object created using ‘new’ operator is of type Derived class. So, at the time of object creation, constructor invocation is from Base class to Derived class. 

• But while deleting pointer Base, compiler cannot tell that Derived class instance is destroyed. Note that ‘delete’ calls the destructor for the class. 

•This problem can be solved by declaring the destructor of the base class as ‘virtual’. In this way, the destructor will be invoked through virtual function table.

Example:

#include<iostream.h>
class Base

{       public: 
      Base()
      {
            cout<<“Base:Constructor”<<endl;
      } 
    ~Base(){
            cout<<“Base:Destructor”<<endl;
      } 
};
class Derived:public Base 

      Derived(){
            cout<<“Derived:Constructor”<<endl;
      } 
      ~Derived(){
           cout<<“Derived:Destructor”<<endl;
      } 
}; 
main()

      Base *base=new Derived; 
      delete base;
}

Output:
Base:Constructor 
Derived:Constructor 
Base:Destructor


After changing Base class destructor as below:
virtual ~Base()

{
    cout<<“Base:Destructor”<<endl;
}

Output: 

Base:Constructor 
Derived:Constructor 
Derived:Destructor 
Base:Destructor 

References in C++

• Reference is an implicit pointer to a variable.
• Creating references: 

        int &r;
• Initializing:
        int i=10;
        int &r=i;
• To access value of a variable using reference
       cout<<r;
• But you cannot use ++, -- like pointers to move references to next location
• References are also const pointers and cannot be reassigned.
       r=&j; is not possible.
• The real need for a reference variable can be felt when we pass by reference variables.

Namespaces in C++

•Namespace is simply a declarative area.
•The purpose of namespace is to localize names of identifiers to avoid name collisions.
•Elements declared in one namespace are separate from elements declared in another.
•Namespace is an important concept for library developer.
•If you include two libraries both having same function prototype, then compiler will be unable to detect which one you are referring to when you invoke it.

Syntax:
•Creating a namespace :
    namespace name{ //declarations}
•Anything defined within a namespace statement is within the scope of that namespace
•Using:
  using namespace name;
 (to include only a particular namespace defined in a library)
•using name::member
 (to include only a particular member of the namespace defined in a library)

Exception Handling in C++

Exception:

An unwanted state during the execution of the program. It can also be defined as “errors at run-time”. 
For example, 
Dividing a number by zero.

Whenever there is an exception in the program, the programmer has two possible solutions: 

a)Resumption- fix the problem and continue
b)Termination-Abort the process and return

In C++,
the Resumption model is supported by the function call mechanism, and 
the Termination model is supported by the exception-handling mechanism

Exception Handling:

“Exception Handling” allows us to manage the exception gracefully. 
Using Exception Handling technique we can avoid abnormal termination of the program and continue with the normal flow or the program, or even move the control to other parts of the program.

Exceptions are handled using try catch statements.

General syntax: 
try{ 

statements;
. . . . . 


catch(type1 arg){statements;}

catch(type2 arg){statements;}

•We can have more than one catch statement associated with a try.


Exception Handling Example:

#include<iostream.h>
void main()

      int j; 
      cin>>j; 
      try
      { 
            if(j==0) throw j; 
               int i=20/j; 
      }catch(int j){ 
            cout<<"Divide by zero"; 
      }catch(...){ 
            cout<<"Caught Exception"; 
      }
}

Output: 
Divide by zero

Re-throwing an Exception:

A re-throw is indicated by a throw without an operand. 

Example;
try{ 
      //code which throws error 
}catch(Error e){ 
      throw; //re-throw 

If a re-throw is attempted when there is no exception to throw , terminate() will be called. 
terminate(), by default, calls abort() to stop the program. But we can specify our own termination handler.

Custom Exception Class:

#include<iostream.h> 
#include<string.h> 

class MyException

{           char *msg; 
          public: 
                  MyException(){
                          msg="MyException";
                  } 
                  MyException(char *m) 
                  {
                          msg=m;
                  } 
                  char* getMessage(){ 
                          return msg;
                  } 

};

void main() 

       int age; 
       try{ 
              cout<<"Enter your age"; 
              cin>>age; 
              if(age>18) 
                     cout<<"Ready to vote"; 
              else{ 
                     MyException e("You are Minor!!"); 
                     throw e;
              } 
       } 
       catch(MyException e) 
       { 
              cout<<"Exception"<<e.getMessage(); 
       }
}

Function Overloading in C++

Function overloading is a feature of C++ that allows us to create multiple functions with the same name, so long as they have different parameters.

You can only overload functions only on the basis of:

  • Type of arguments
  • Number of arguments
  • Sequence of arguments &
  • Qualifiers like const and volatile.
Consider the following function:
        int Add(int x, int y)
       {
                return x+ y;
       }
This trivial function adds two integers. However, what if we also need to add two floating point numbers? This function is not at all suitable.Again we have to write one more function with float variables.
One way to work around this issue is to define multiple functions with slightly different names:
      int AddI(int x, int y)
     {
              return x+ y;
     }
     double AddD(double x, double y)
     {
             return x+ y;
     }

Function overloading provides a better solution
We now have two version of Add():
      int Add(int nX, int nY); // integer version
      double Add(double dX, double dY); // floating point version

Which version of Add() gets called depends on the arguments used in the call — if we provide two ints, C++ will know we mean to call Add(int, int). If we provide two floating point numbers, C++ will know we mean to call Add(double, double). In fact, we can define as many overloaded Add() functions as we want, so long as each Add() function has unique parameters.

Making a call to an overloaded function results in one of three possible outcomes:
1) A match is found. The call is resolved to a particular overloaded function.
2) No match is found. The arguments can not be matched to any overloaded function.
3) An ambiguous match is found. The arguments matched more than one overloaded function.


When an overloaded function is called, C++ goes through the following process to determine which version of the function will be called:

1) First, C++ tries to find an exact match. This is the case where the actual argument exactly matches the parameter type of one of the overloaded functions. For example:
          void Print(char *szValue);
          void Print(int nValue);

          Print(0); // exact match with Print(int)


Although 0 could technically match Print(char*), it exactly matches Print(int). Thus Print(int) is the best match available.

2) If no exact match is found, C++ tries to find a match through promotion.

To summarize,

  • Char, unsigned char, and short is promoted to an int.
  • Unsigned short can be promoted to int or unsigned int, depending on  
       the size of an int.

  • Float is promoted to double
  • Enum is promoted to int

For example:

         void Print(char *szValue);
         void Print(int nValue);
        
         Print('a'); // promoted to match Print(int)

In this case, because there is no Print(char), the char ‘a’ is promoted to an integer, which then matches Print(int).

3) If no promotion is found, C++ tries to find a match through standard conversion. 


Standard conversions include:

  • Any numeric type will match any other numeric type, including unsigned (eg. int to float)
  • Enum will match the formal type of a numeric type (eg. enum to float)
  • Zero will match a pointer type and numeric type (eg. 0 to char*, or 0 to float)
  • A pointer will match a void pointer

For example:
         void Print(float fValue);
         void Print(struct sValue);

         Print('a'); // promoted to match Print(float)


In this case, because there is no Print(char), and no Print(int), the ‘a’ is converted to a float and matched with Print(float).

Note that all standard conversions are considered equal. No standard conversion is considered better than any of the others.

Ambiguous matches:

class A


        public: 
               void foo(int x) 
               {
                  cout << "foo with one\n"; 
               } 
               void foo(int x, int y=10) 
               { 
                  cout << "foo with two\n";
               } 

}; 
int main() 


      A a; 
      a.foo(1); //error? 
}

Because function/operator overloading is resolved by compiler at compile time. So overloading a function just by providing a default argument will cause ambiguity and compiler error.

Stack Overflow Situation

func_call() {
           funct_call();
}

Every time the above function is called the return address is stored onto the stack. Calling in this infinite loop will cause a stack overflow.

Examples for an infinite loop

a. while (1)
   {
   }

b. for (;;)

   {
   }

c. do

   {
   }while(1);

d. label:
    goto label;

Standard prototypes for main() function

a. int main (void)
b. int main (int argc, char **argv)
c. int main (int argc, char *argv[])

C++ Features Not in C

Listed below are some features that are found in C++, not found in C, but still have nothing to do with Object Oriented Programming.

Casts:
In C, if you want to cast an int to a long int, for example, you'd use 
int i=0; 
long l = (long) i; 

In C++, you can use a function-like call to make the cast. 
long l = long(i);

It's easier to read. Since it's possible to create functions to perform casts involving user-defined types, this makes all the casts look consistent. For example, you may have a user-defined type -- complex numbers. 

You have a function that accepts an integer and casts it to a complex number: 1 --> 1 + 0i (real part is 1 and imaginary part is 0) 

Suppose your function call is named 'complex', then it may look like: 

Complex x;
int i=1; 
 x = complex(i);

Flexible Declarations:
In C, all var declarations within a scope occur at the beginning of that scope. Thus, all global declartions must appear before any functions, and any local declarations must be made before any executable statements.

C++, on the other hand, allows you to mix data declarations with functions and executable statements. 

E.g. In C,
void makeit(void) 
{
      float i; 
      char *cp;
      /* imagine 2000 lines of code here */ 
      /* allocate 100 bytes for cp */ 
      cp = malloc(100); /* 1st use of cp */ 
      for (i=0; i<100; ++i) /* 1st use of i */ 
      { 
              /* do something */ 
      } /* more code */ 
 } 

In C++, 
void makeit(void) 
      // 2000 lines of code 
      char *cp = new char[100]; 
      for (int i=1; i<10; i++) { } 
}

'struct' and 'union' Tags:

In C, we would have this segment: 
struct foo 
{
      int a; 
      float b;
struct foo f; 

This declares a struct with the tag name 'foo' and then creates an instance of foo named f. Notice when you declare var of that struct, you have to say 'struct foo'. 
In C++, struct and union tags are considered to be type name, just as if they had been declared by the 'typedef' statement. 

struct foo {int a; float b;}
foo f; 

which is equivalent to the following in C: 
typedef struct 
      int a; 
      float b; 
} foo;

foo f;


'const':

In ANSI C, it also supports 'const', but C++'s 'const' is more flexible than C's. In both C and C++, a value declared as 'const' is inviolate; it may not be modified by any part of the program in any way. 
The most common use of 'const' values in C is to replace '#define' literal constants. 

#define MAX_CUSTOMERS 10 
 const int MAX_CUSTOMERS = 10; 

Thus, 
MAX_CUSTOMERS = 10; 
MAX_CUSTOMERS ++; 

are both not acceptable. Note: since you cannot make changes to a 'const', each constant must be initialized when declared. The following is wrong: 
const int invalid; 

In C++, you can do something like 
const int ArraySize = 100;
int Array[ArraySize];
while in ANSI C, this would be flagged as an error.

'new' and 'delete':

In C, all dynamic mem allocation is handled via library calls, such as 'malloc' and 'free'. Here's how a traditional C programs might allocate memory: 

void func(void) 
{
     int *i; 
     i = (int *)malloc(sizeof(int)); 
    *i = 10; 
     printf("%d", *i); 
     free(i); 

In C++, there are new ways of dynamically allocating mem using operators called 'new' and 'delete', where 'new' replaces 'malloc' and 'delete' replaces 'free' in C. We could rewrite the above function as the following: 

void func() 
     int *i = new int; 
     *i = 10; 
     cout << *i; 
     delete i; 
}
You'd probably agree this is a much clearer syntax and it's much easier to use as well. 

A couple more examples: 
     int *i = new int[10]; // an array of 10 integers 
     int *i = new int(*)[10]; // an array of 10 pointers to integers 

You can also intialize all the variables allocated by 'new': 

float *f = new float[50] (0.0); 

Error Code: if 'new' fails to allocate any memory requested, it will return NULL;
Tip: Usually, right after a call to allocate memory, 'new' or 'malloc' check to see if any memory has been allocated. This can prevent your program from accessing a NULL pointer which is a disaster and which will cause a bus error.

Note: Don't mix the use of 'new' and 'delete' with that of 'malloc' and 'free'. i.e, always use either all the C lib calls 'malloc' and 'free' in your program to manage dynamic mem. OR use all 'new' and 'delete'. All the mem allocated by 'malloc' should be returned to the available mem pool by 'free' and the same holds for 'new' and 'delete'. I'd just use 'new' and 'delete'.

References:

C can by clumsy sometimes. When you write a function to swap two integers, you have to pass the two integers into the function by reference: 

void swapint(int *a, int *b) 
      int temp;
      temp = *a; 
      *a = *b; 
      *b = temp; 
}
Here's the function call: 
    swapint(&i1, &i2); 

C++ supports a special type of identifier known as 'reference' &. It makes changing the parameter values in a function reletively painless. The above function can be rewritten in C++ as follows: 

void swapint(int &a, int &b) 
     int temp = a; 
     a = b; 
     b = temp; 
Function call: 
     swapint(i1, i2); 

When i1 and i2 are passed into the function, a POINTS to i1 and b POINTS to i2 instead of making local copies of i1 and i2. Now, whenever you refer to a or b in the function, you actually refer to i1 and i2. So, whatever changes you make to a or b, they will be reflected on i1 and i2.


Function Overloading:

In C, as in most other programming languages, every function must have a unique name. At times, it can be annoying. Imagine you want to have a function that returns the abs value of an integer. 
int abs(int i); 

If you need to figure out the abs value of every possible available data type, you then have to write a function for each of the possible types: 

long labs(long l);
double dabs(double d); 

All those functions do the same thing -- return the abs value of the argument. Thus it seems silly to have a different name for each of those functions. 

C++ solves this by allowing you to create those functions with the same name. This is called overloading. 

For example, you can do the above in C++: 
int abs(int i); 
long abs(long l); 
double abs(double d); 

And depending on the type of parameter you pass into the 'abs' func. C++ will select the right one. 

Note: What if the type of the parameter passed in is not identical to any of the available parameter types in the existing functions? 

abs('a'); 
abs(3.1415F); 

C++ will try to make the easiest conversion to match those parameter types in the funcion prototypes. 

abs('a'); // call int abs(int i) 
abs(3.1415F); // call double abs(double d);
If no such conversion exists, then an error will occur.

C,C++ Quiz

1. Base class has some virtual method and derived class has a method with the same name. If we initialize the base class pointer with derived object,. calling of that virtual method will result in which method being called?
a. Base method 
b. Derived method..

Ans: b


2. For the following C program 
#define AREA(x)(3.14*x*x)
main()
{

        float r1=6.25,r2=2.5,a;
        a=AREA(r1);
        printf("\n Area of the circle is %f", a);
        a=AREA(r2);
        printf("\n Area of the circle is %f", a);
}

What is the output? 

Ans:
Area of the circle is 122.656250
Area of the circle is 19.625000

3.void main()  {
       int d=5;
       printf("%f",d);
  }

Ans: Undefined


4.void main()
{
     int i;
     for(i=1;i<4,i++)
     switch(i)
             case 1: printf("%d",i);break;
             {
             case 2:printf("%d",i);break;
             case 3:printf("%d",i);break;
             }
             switch(i) 

                      case 4:printf("%d",i);
}

Ans: 1,2,3,4

5.void main()
  {
          char *s="\12345s\n";
          printf("%d",sizeof(s));
  }

Ans: 6

6.void main()
  {
           unsigned i=1; /* unsigned char k= -1 => k=255; */
           signed j=-1; /* char k= -1 => k=65535 */
           /* unsigned or signed int k= -1 =>k=65535 */
           if(i<j)
                  printf("less");
           else
                  if(i>j)
                          printf("greater");
                  else
                          if(i==j)
                          printf("equal");
  }

Ans: less


7.void main()   {
          float j;
          j=1000*1000;
          printf("%f",j);
   }

1. 1000000
2. Overflow
3. Error
4. None 


Ans: 4

8.int f()  void main()
  {
       f(1);
       f(1,2);
       f(1,2,3);
  }
  f(int i,int j,int k)
  {
       printf("%d %d %d",i,j,k);
  }
What are the number of syntax errors in the above?

Ans: None.

9.void main() 

  {
        int i=7;
        printf("%d",i++*i++);
  }

Ans: 56

10.#define one 0 
    #ifdef one
    printf("one is defined ");
    #ifndef one
     printf("one is not defined ");
Ans: "one is defined"

11.void main() 
    {
           int count=10,*temp,sum=0;
           temp=&count;
           *temp=20;
           temp=&sum;
           *temp=count;
           printf("%d %d %d ",count,*temp,sum);
   }

Ans: 20 20 20




12.what is alloca()

Ans : It allocates and frees memory after use/after getting out of scope

13.main() 
    {
         static i=3;
         printf("%d",i--);
         return i>0 ? main():0;
    }

Ans: 321

14.char *foo() 
    {
         char result[100]);
         strcpy(result,"anything is good");
         return(result);
    }
    void main()
    {
         char *j;
         j=foo()
         printf("%s",j);
    }

Ans: anything is good.

Can I mix C-style and C++ style allocation and deallocation?

Yes, in the sense that you can use malloc() and new in the same program.

No, in the sense that you cannot allocate an object with malloc() and free it using delete. Nor can you allocate with new and delete with free() or use realloc() on an array allocated by new.

The C++ operators new and delete guarantee proper construction and destruction; where constructors or destructors need to be invoked, they are. The C-style functions malloc(), calloc(), free(), and realloc() doesn't ensure that. Furthermore, there is no guarantee that the mechanism used by new and delete to acquire and release raw memory is compatible with malloc() and free(). If mixing styles works on your system, you were simply "lucky" - for now.

If you feel the need for realloc() - and many do - then consider using a standard library vector. 

For example // read words from input into a vector of strings:

vector<string> words;
string s;
while (cin>>s && s!=".") words.push_back(s);


The vector expands as needed.

Copy Constructor in C++

Copy constructor is a constructor function with the same name as the class used to make copy of objects.

There are 3 important places where a copy constructor is called -

1)When an object is created from another object of the same type
2)When an object is passed by value as a parameter to a function
2)When an object is returned from a function

If a copy constructor is not defined in a class, the compiler itself defines one. This will ensure a shallow copy. If the class does not have pointer variables with dynamically allocated memory, then one need not worry about defining a copy constructor. It can be left to the compiler's discretion.
But if the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor. 

For ex:

                    class A //Without copy constructor
                    {
                         private:
                                   int x;
                         public:
                                   A() 
                                   {
                                          A = 10;
                                   }
                                   ~A() 
                                   {
                                   }
                    }
                   class B //With copy constructor
                    {
                        private:
                                  char *name;
                        public:
                                   B()
                                   {
                                         name = new char[20];
                                   }
                                   ~B()
                                   {
                                         delete name[];
                                   }
                                 //Copy constructor
                                  B(const B &b)
                                  {
                                         name = new char[20];
                                         strcpy(name, b.name);
                                   }
                     };

Let us Imagine if we don't have a copy constructor for the class B. At the first place, if an object is created from some existing object, we cannot be sure that the memory is allocated. Also, if the memory is deleted in destructor, the delete operator might be called twice for the same memory location. 

This is a major risk. One thing is, if the class is not so complex this will come to the fore during development itself. But if the class is very complicated, then these kind of errors will be difficult to track.
We all know that compiler will generate default constructor, destructor, copy constructor and copy assignment = operator by default if we dont define in our class definitions. 
Assume that, there is a scenario where we should not allow copy constructor and copy assignment operator in the program. 
Lets take some example, 
class A {/*...*/}; 
int main() 

        A a; /* default constructor */ 
        A b(a); /* copy constructor.. We should not allow this */ 
        b = a; /* copy assignment operator.. we should not allow this */ 

How do you achieve this? 

You can acheive this by making your copy constructor and assignment operator private.
here is your modified code 

class A 
{/*... 
      private : 
                 A(const A& ) 
                 { 
                 } 
                 A& operator=(const A ) 
                 { 
                 }
*/};
int main()
{
     A a; /* default constructor */
     A b(a); /* copy constructor.. We should not allow this */
     b = a; /* copy assignment operator.. we should not allow this */
}

now you will get compilation error saying copy constructor and assignment operator are private members.

You are right. You can have these in private and you don't have to implement that.
class A 

     private: 
               A(const A&);
               A& operator=(const A&);
     public: 

The difference between shallow and deep copying is only relevant for compound objects. (i.e objects that contain other objects, like lists/class instances or if objects has pointers to dynamically allocated memory). 


A shallow copy is bitwise copy of any object.
A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

Thus 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 should be sufficient.
If there are compound objects, then one has to define their own copy constructors, assignment operator and destructors for deep copy.

For Example:

// Shallow copy

Class Test
{       public:
              Test( int a, float b )
              {
                     i = a;
                     j = b;
               }
      private:
               int i;
               float j;
}
Test t1( 10, 20.0 );
Test t2(t1); // In this case, shallow copy is sufficient.


// Deep Copy

Class Test
{       public:
               Test( int a, char* s )
               {
                      i = a;
                      int len = strlen(s);
                      str = new char[len+1];
               }
      private:
                int i;
                char* str;
}
Test t1( 10, "Test" );
Test t2(t1); // In this case, deep copy is needed.