Sunday, May 30, 2010

Inheritance

INHERITANCE
Inheritance is the process of creating new classes from the existing class or classes.
Reusability) .
Using inheritance, one can create general class that defines traits common to a set of related items. This class can then be inherited (reused) by the other classes by using the properties of the existing ones with the addition of its own unique properties.

Inheritance can be done in different ways:
1. Single Inheritance - no quite
2. Multiple Inheritance
3. Multi-Level Inheritance
4. Hybrid Inheritance and
5. Hierarchial Inheritance.

The old class is referred to as the base class and the new classes, which are inherited from the base class, are called derived classes.


In above figure, the class B contains the three member i.e. Property1, Property2 and Property3.

The second class named as D contains four members i.e. Property1, Property2, Property3 and Property4.

Out of these, three members (Property1, Property2, Property3) of the class D are same as that of class B, while the one member i.e. Property4 is unique.

In the class D, instead of defining all the three members again, one can reuse them from the class B. This feature is known as inheritance which saves time, space, money and increases the reliability and efficiency.

Forms of Inheritance

1.) Single Inheritance

If a class is derived from a single base class, it is called as single inheritance.

2 .) Multiple Inheritance

If a class is derived from more than one base class, it is known as multiple inheritance

3 ) Multilevel Inheritance

The classes can also be derived from the classes that are already derived. This type of inheritance is called multilevel inheritance.

4 ) Hierarchical Inheritance

If a number of classes are derived from a single base class, it is called as hierarchical inheritance

A derived class can be defined as follows:

class derived_class_name : access_specifier base_class_name
{
data members of the derived class ;
member functions of the derived class ;
}

The colon (:), indicates that the class derived_class_name is derived from the class base_class_name.

The access_specifier may be public, private or protected (will be discussed further).

If no access_specifier is specified, it is private by default.

The access_specifier indicates whether the members of the base class are privately derived or publicly derived.


Public inheritance

When a derived class publicly inherits the base class, all the public members of the base class also become public to the derived class and the objects of the derived class can access the public members of the base class.

The following program will illustrate the use of the single inheritance.

This program has a base class B, from which class D is inherited publicly.

Example:

#include
class Rectangle
{
private:
float length ; // This can't be inherited
public:
float breadth ; // The data and member functions are inheritable
void Enter_lb(void)
{
cout << "\n Enter the length of the rectangle : ";
cin >> length ;
cout << "\n Enter the breadth of the rectangle : ";
cin >> breadth ;
}
float Enter_l(void)
{ return length ; }
}; // End of the class definition

class Rectangle1 : public Rectangle
{
private:
float area ;
public:
void Rec_area(void)
{ area = Enter_l( ) * breadth ; }
// area = length * breadth ; can't be used here

void Display(void)
{
cout << "\n Length = " << Enter_l( ) ; // Object of the derived class can't
// inherit the private member of the base class. Thus the member
// function is used here to get the value of data member 'length'.
cout << "\n Breadth = " << breadth ;
cout << "\n Area = " << area ;
}
}; // End of the derived class definition D
void main(void)
{
Rectangle1 r1 ;
r1.Enter_lb( );
r1.Rec_area( );
r1.Display( );
}




























Private inheritance

When a derived class privately inherits a base class, all the public members of the base class become private for the derived class.

In this case, the public members of the base class can only be accessed by the member functions of the derived class.

The objects of the derived class cannot access the public members of the base class.

Note that whether the derived class is inherited publicly or privately from the base class, the private members of the base class cannot be inherited.


Example:

#include
#include
class Rectangle
{
int length, breadth;
public:
void enter()
{
cout << "\n Enter length: "; cin >> length;
cout << "\n Enter breadth: "; cin >> breadth;
}
int getLength()
{
return length;
}
int getBreadth()
{
return breadth;
}
void display()
{
cout << "\n Length= " << length;
cout << "\n Breadth= " << breadth;
}
};

class RecArea : private Rectangle
{

public:
void area_rec()
{
enter();
cout << "\n Area = " << (getLength() * getBreadth());
}
};
void main()
{
clrscr();
RecArea r ;
r.area_rec();
getch();
}

Example:2

#include
class Rectangle // Base class
{
private:
float length ; // This data member can't be inherited
public:
float breadth ; // This data member is inheritable
void Enter_lb(void)
{
cout << "\n Enter the length of the rectangle: "; cin >> length ;
cout << "\n Enter the breadth of the rectangle: "; cin >> bredth ;
}
float Enter_l(void)
{
return length ;
}
void Display_l(void)
{
cout << "\n Length = " << length ;
}
}; // End of the base class Rectangle.
// Defining the derived class Rectangle1. This class has been derived from the
// base class i.e. Rectangle, privately.
class Rectangle1 : private Rectangle // All the public members of the base class
{ // Rectangle become private for the derived class Rectangle1.
private:
float area ;
public:
void Rec_area(void)
{
Enter_lb( );
area = Enter_l( ) * bredth ; // length can't be used directly
}
void Display(void)
{
Display_l( ); // Displays the value of length.
cout << "\n Bredth = " << bredth ;
cout << "\n Area = " << area << endl ;
}
};
void main(void)
{
Rectangle1 r1 ;
r1.Rec_area( ) ;
// r.Enter_lb( ); will not work as it has become private for the derived class.
r1.Display( ) ;
// r.Display_l( ) will not work as it also has become private for the derived class.
}




The protected access specifier

The third access specifier provided by C++ is protected.

The members declared as protected can be accessed by the member functions within their own class and any other class immediately derived from it.

These members cannot be accessed by the functions outside these two classes.

Therefore, the objects of the derived class cannot access protected members of the base class.

When the protected members (data, functions) are inherited in public mode, they become protected in the derived class. Thus, they can be accessed by the member functions of the derived class.

On other hand, if the protected members are inherited in the private mode, the members also become private in the derived class.

They can also be accessed by the member functions of the derived class, but cannot be inherited further.

Overriding the member functions:

The member functions can also be used in a derived class, with the same name as those in the base class.

One might want to do this so that calls in the program work the same way for objects of both base and derived classes.

The following program will illustrate this concept.

#include
const int len = 20 ;
class Employee
{
private:
char F_name[len];
int I_number ;
int age ;
float salary ;
public:
void Enter_data(void)
{
cout << "\n Enter the first name = " ; cin >> F_name ;
cout << "\n Enter the identity number = " ; cin >> I_number ;
cout << "\n Enter the age = " ; cin >> age ;
cout << "\n Enter the salary = " ; cin >> salary ;
}
void Display_data(void)
{
cout << "\n Name = " << F_name ;
cout << "\n Identity Number = " << I_number ;
cout << "\n Age = " << age ;
cout << "\n Salary = " << salary ;
}
}; // End of the base class
class Engineer : public Employee
{
private:
char design[len] ; // S_Engineer, J_Engineer, Ex_Engineer etc

public:
void Enter_data( )
{
Employee :: Enter_data( ) ; // Overriding of the member function
cout << "\n Enter the designation of the Engineer: " ; cin >> design ;
}


void Display_data(void)
{
cout << "\n *******Displaying the particulars of the Engineer**** \n" ;
Employee :: Display_data( ) ; // Overriding of the member function
cout << "\n Designition = " << design ;
}
}; // End of the derived class

void main(void)
{
Engineer er ;
er.Enter_data( ) ;
er.Display_data( );
}

Hierarchical Inheritance:

When two or more classes are derived from a single base class, then
Inheritance is called the hierarchical inheritance. The representation
of the hierarchical inheritance is shown in the following Fig.









In the above Fig., student is a base class, from which the three classes viz. arts, science and commerce have been derived. Now, let us write a program that illustrates the hierarchical inheritance, based on the above design.

Example

include
const int len = 20 ;
class student // Base class
{
private: char F_name[len] , L_name[len] ;
int age, int roll_no ;
public:
void Enter_data(void)
{
cout << "\n\t Enter the first name: " ; cin >> F_name ;
cout << "\t Enter the second name: "; cin >> L_name ;
cout << "\t Enter the age: " ; cin >> age ;
cout << "\t Enter the roll_no: " ; cin >> roll_no ;
}
void Display_data(void)
{
cout << "\n\t First Name = " << F_name ;
cout << "\n\t Last Name = " << L_name ;
cout << "\n\t Age = " << age ;
cout << "\n\t Roll Number = " << roll_no ;
}
};
class arts : public student
{
private:
char asub1[len] ;
char asub2[len] ;
char asub3[len] ;
public:
void Enter_data(void)
{
student :: Enter_data( );
cout << "\t Enter the subject1 of the arts student: "; cin >> asub1 ;
cout << "\t Enter the subject2 of the arts student: "; cin >> asub2 ;
cout << "\t Enter the subject3 of the arts student: "; cin >> asub3 ;
}
void Display_data(void)
{
student :: Display_data( );
cout << "\n\t Subject1 of the arts student = " << asub1 ;
cout << "\n\t Subject2 of the arts student = " << asub2 ;
cout << "\n\t Subject3 of the arts student = " << asub3 ;
}
};
class commerce : public student
{
private: char csub1[len], csub2[len], csub3[len] ;
public:
void Enter_data(void)
{
student :: Enter_data( );
cout << "\t Enter the subject1 of the commerce student: ";
cin >> csub1;
cout << "\t Enter the subject2 of the commerce student: ";
cin >> csub2 ;
cout << "\t Enter the subject3 of the commerce student: ";
cin >> csub3 ;
}
void Display_data(void)
{
student :: Display_data( );
cout << "\n\t Subject1 of the commerce student = " << csub1 ;
cout << "\n\t Subject2 of the commerce student = " << csub2 ;
cout << "\n\t Subject3 of the commerce student = " << csub3 ;
}
};

void main(void)
{
arts a ;
cout << "\n Entering details of the arts student\n" ;
a.Enter_data( );
cout << "\n Displaying the details of the arts student\n" ;
a.Display_data( );
science s ;
cout << "\n\n Entering details of the science student\n" ;
s.Enter_data( );
cout << "\n Displaying the details of the science student\n" ;
s.Display_data( );
commerce c ;
cout << "\n\n Entering details of the commerce student\n" ;
c.Enter_data( );
cout << "\n Displaying the details of the commerce student\n";
c.Display_data( );
}

Multiple Inheritance

When a class is inherited from more than one base class, it is known as multiple inheritance.
The syntax for defining a subclass, which is inheriting more than one classes is:
class Subclass : access_specifier Baseclass1,
access_specifier Baseclass2, ………
…….. access_specifier Baseclass_n
{
members of the derived class ;
};
The following figure illustrates the use of multiple inheritance. 




















In the above figure, Circle and Rectangle are two base classes from which the class Cylinder is being inherited.

The data members of both the base classes are declared in protected mode. Thus, the class Cylinder can access the data member radius of class Circle and data member length, breadth of the class Rectangle, but the objects of the class Cylinder cannot access these protected data members.

The volume of the cylinder is equal to 22/7*(radius*radius*length). Thus, instead of defining these data again, they can be inherited from the base classes Circle and Rectangle ( radius from class Circle and length from class Rectangle ).

Example:

#include
class Circle // First base class
{
protected:
float radius ;
public:
void Enter_r(void)
{
cout << "\n\t Enter the radius: "; cin >> radius ;
}
void Display_ca(void)
{
cout << "\t The area = " << (22/7 * radius*radius) ;
}
};
class Rectangle // Second base class
{
protected:
float length, breadth ;
public:
void Enter_lb(void)
{
cout << "\t Enter the length : "; cin >> length ;
cout << “\t Enter the breadth : ” ; cin >> breadth ;
}
void Display_ar(void)
{
cout << "\t The area = " << (length * breadth);
}
};
class Cylinder : public Circle, public Rectangle // Derived class, inherited
{ // from classes Circle & Rectangle
public:
void volume_cy(void)
{
cout << "\t The volume of the cylinder is: "
<< (22/7* radius*radius*length) ;
}
};
void main(void)
{
Circle c ;
cout << "\n Getting the radius of the circle\n" ;
c.Enter_r( );
c.Display_ca( );
Rectangle r ;
cout << "\n\n Getting the length and breadth of the rectangle\n\n";
r.Enter_l( );
r.Enter_b( );
r.Display_ar( );
Cylinder cy ; // Object cy of the class cylinder which can access all the
// public members of the class circle as well as of the class rectangle
cout << "\n\n Getting the height and radius of the cylinder\n";
cy.Enter_r( );
cy.Enter_lb( );
cy.volume_cy( );
}

Multilevel Inheritance:

It has been discussed so far that a class can be derived from a class.

C++ also provides the facility of multilevel inheritance, according to which the derived class can also be derived by an another class, which in turn can further be inherited by another and so on.

The following figure will illustrate the meaning of the multilevel inheritance.































In the above figure, class B represents the base class. The class D1 that is called first level of inheritance, inherits the class B. The derived class D1 is further inherited by the class D2, which is called second level of inheritance.

Example: Multilevel Inheritance

#include
class Base
{
protected:
int b;
public:
void EnterData( )
{
cout << "\n Enter the value of b: ";
cin >> b;
}
void DisplayData( )
{
cout << "\n b = " << b;
}
};
class Derive1 : public Base
{
protected:
int d1;
public:
void EnterData( )
{
Base:: EnterData( );
cout << "\n Enter the value of d1: ";
cin >> d1;
}
void DisplayData( )
{
Base::DisplayData();
cout << "\n d1 = " << d1;
}
};
class Derive2 : public Derive1
{
private:
int d2;
public:
void EnterData( )
{
Derive1::EnterData( );
cout << "\n Enter the value of d2: ";
cin >> d2;
}
void DisplayData( )
{
Derive1::DisplayData( );
cout << "\n d2 = " << d2;
}
};
int main( )
{
Derive2 objd2;
objd2.EnterData( );
objd2.DisplayData( );
return 0;
}

*****************************************************************************

Virtual base classes

Suppose you have two derived classes B and C that have a common base class A, and you also have another class D that inherits from B and C. You can declare the base class A as virtual to ensure that B and C share the same subobject of A.
In the following example, an object of class D has two distinct subobjects of class L, one through class B1 and another through class B2. You can use the keyword virtual in front of the base class specifiers in the base lists of classes B1 and B2 to indicate that only one subobject of type L, shared by class B1 and class B2, exists.
  






class L { /* ... */ }; // indirect base class
class B1 : virtual public L { /* ... */ };
class B2 : virtual public L { /* ... */ };
class D : public B1, public B2 { /* ... */ }; // valid
Using the keyword virtual in this example ensures that an object of class D inherits only one subobject of class L.
A derived class can have both virtual and nonvirtual base classes. For example:





class V { /* ... */ };
class B1 : virtual public V { /* ... */ };
class B2 : virtual public V { /* ... */ };
class B3 : public V { /* ... */ };
class X : public B1, public B2, public B3 { /* ... */
};
In the above example, class X has two subobjects of class V, one that is shared by classes B1 and B2 and one through class B3.



Example of  Hybrid or Virtual Base Class

class PoweredDevice
{
public:
    PoweredDevice(int nPower)
    {
               cout << "PoweredDevice: " << nPower << endl;
    }
};
 
class Scanner: virtual public PoweredDevice
{
public:
    Scanner(int nScanner, int nPower)
        : PoweredDevice(nPower)
    {
               cout << "Scanner: " << nScanner << endl;
    }
};
 
class Printer: virtual public PoweredDevice
{
public:
    Printer(int nPrinter, int nPower)
        : PoweredDevice(nPower)
    {
               cout << "Printer: " << nPrinter << endl;
    }
};
 
class Copier: public Scanner, public Printer
{
public:
    Copier(int nScanner, int nPrinter, int nPower)
        : Scanner(nScanner, nPower), Printer(nPrinter, nPower), PoweredDevice(nPower)
    {
    }
};

int main()
{
    Copier cCopier(1, 2, 3);
}
Output :
produces the result:
PoweredDevice: 3
Scanner: 1
Printer: 2
 

Virtual functions

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 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 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 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 AClass 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 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.
 


Abstract classes

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(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.


Thursday, May 27, 2010

STL(Standard Template Library)

The Standard Template Libraries (STL's) are a set of C++ template classes to provide common programming data structures and functions such as doubly linked lists (list), paired arrays (map), expandable arrays (vector), large string storage and manipulation (rope), etc.

STL can be categorized into the following groupings:
  • Container classes:





    • Sequences:





      • vector: (this tutorial) Dynamic array of variables, struct or objects. Insert data at the end.

      • deque: Array which supports insertion/removal of elements at beginning or end of array
      • list: (this tutorial) Linked list of variables, struct or objects. Insert/remove anywhere.
    • Associative Containers:





      • set (duplicate data not allowed in set), multiset (duplication allowed): Collection of ordered data in a balanced binary tree structure. Fast search.
      • mqp(unique keys), multimap (duplicate keys allowed): Associative key-value pair held in balanced binary tree structure.
    • Container adapters:





      • stack LIFO
      • queue FIFO
      • priority_queue returns element with highest priority.
    • String:





      • string: Character strings and manipulation
      • rope: String storage and manipulation
    • bitset: Contains a more intuitive method of storing and manipulating bits.
  • Operations/Utilities:





    • iterator: (examples in this tutorial) STL class to represent position in an STL container. An iterator is declared to be associated with a single container class type.
    • algorithm: Routines to find, count, sort, search, ... elements in container classes
    • auto_ptr: Class to manage memory pointers and avoid memory leaks.
    •  


1.) Vector
Vectors are a kind of sequence containers. As such, their elements are ordered following a strict linear sequence.

Vector containers are implemented as dynamic arrays; Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements.
Vectors are good at:

  • Accessing individual elements by their position index (constant time).
  • Iterating over the elements in any order (linear time).
  • Add and remove elements from its end (constant amortized time).
Example 

// vector::begin
#include 
#include 
using namespace std;

int main ()
{
  vector<int> myvector;
  for (int i=1; i<=5; i++) myvector.push_back(i);

  vector<int>::iterator it;

  cout << "myvector contains:";
  for ( it=myvector.begin() ; it < myvector.end(); it++ )
    cout << " " << *it;

  cout << endl;

  return 0;

}
Output:

myvector contains: 1 2 3 4 5 
 
*******************************************************************
 
// comparing size, capacity and max_size
#include 
#include 
using namespace std;

int main ()
{
  vector<int> myvector;

  // set some content in the vector:
  for (int i=0; i<100; i++) myvector.push_back(i);

  cout << "size: " << (int) myvector.size() << "\n";
  cout << "capacity: " << (int) myvector.capacity() << "\n";
  cout << "max_size: " << (int) myvector.max_size() << "\n";
  return 0;
}

A possible output for this program could be:

size: 100
capacity: 141
max_size: 1073741823

************************************************************************
// vector::push_back
#include 
#include 
using namespace std;

int main ()
{
  vector<int> myvector;
  int myint;

  cout << "Please enter some integers (enter 0 to end):\n";

  do {
    cin >> myint;
    myvector.push_back (myint);
  } while (myint);

  cout << "myvector stores " << (int) myvector.size() << " numbers.\n";

  return 0;
}

*****************************************************************************

list

List
Lists are a kind of sequence containers. As such, their elements are ordered following a linear sequence.

List containers are implemented as doubly-linked lists; Doubly linked lists can store each of the elements they contain in different and unrelated storage locations. The ordering is kept by the association to each element of a link to the element preceding it and a link to the element following it.

This provides the following advantages to list containers:
  • Efficient insertion and removal of elements anywhere in the container (constant time).
  • Efficient moving elements and block of elements within the container or even between different containers (constant time).
  • Iterating over the elements in forward or reverse order (linear time).
Example

// inserting into a list
#include 
#include 
#include 
using namespace std;

int main ()
{
  list<int> mylist;
  list<int>::iterator it;

  // set some initial values:
  for (int i=1; i<=5; i++) mylist.push_back(i); // 1 2 3 4 5

  it = mylist.begin();
  ++it;       // it points now to number 2           ^

  mylist.insert (it,10);                        // 1 10 2 3 4 5

  // "it" still points to number 2                      ^
  mylist.insert (it,2,20);                      // 1 10 20 20 2 3 4 5

  --it;       // it points now to the second 20            ^

  vector<int> myvector (2,30);
  mylist.insert (it,myvector.begin(),myvector.end());
                                                // 1 10 20 30 30 20 2 3 4 5
                                                //               ^
  cout << "mylist contains:";
  for (it=mylist.begin(); it!=mylist.end(); it++)
    cout << " " << *it;
  cout << endl;

  return 0;
}

 Output:

mylist contains: 1 10 20 30 30 20 2 3 4 5
********************************************************************************
// list::begin
#include 
#include 
using namespace std;

int main ()
{
  int myints[] = {75,23,65,42,13};
  list<int> mylist (myints,myints+5);

  list<int>::iterator it;

  cout << "mylist contains:";
  for ( it=mylist.begin() ; it != mylist.end(); it++ )
    cout << " " << *it;

  cout << endl;

  return 0;
} 
 
Output:

mylist contains: 75 23 65 42 13
***************************************************************************
// reversing vector
#include 
#include 
using namespace std;

int main ()
{
  list<int> mylist;
  list<int>::iterator it;

  for (int i=1; i<10; i++) mylist.push_back(i);

  mylist.reverse();

  cout << "mylist contains:";
  for (it=mylist.begin(); it!=mylist.end(); ++it)
    cout << " " << *it;

  cout << endl;

  return 0;
}
 
Output:

mylist contains: 9 8 7 6 5 4 3 2 1
********************************************************************************
Member Function of List are as follows
list::assign
list::back
list::begin
list::clear
list::empty
list::end
list::erase
list::front
list::get_allocator
list::insert
list::max_size
list::merge
list::operator=
list::pop_back
list::pop_front
list::push_back
list::push_front
list::rbegin
list::remove
list::remove_if
list::rend
list::resize
list::reverse
list::size
list::sort
list::splice
list::swap
list::unique
****************************************************************************
Map
Maps are a kind of associative containers that stores elements formed by the combination of a key value and a mapped value.

In a map, the key value is generally used to uniquely identify the element, while the mapped value is some sort of value associated to this key. Types of key and mapped value may differ. For example, a typical example of a map is a telephone guide where the name is the key and the telephone number is the mapped value.


Example:


// map::begin/end
#include 
#include 
using namespace std;

int main ()
{
  map<char,int> mymap;
  map<char,int>::iterator it;

  mymap['b'] = 100;
  mymap['a'] = 200;
  mymap['c'] = 300;

  // show content:
  for ( it=mymap.begin() ; it != mymap.end(); it++ )
    cout << (*it).first << " => " << (*it).second << endl;

  return 0;
}
output 

a => 200
b => 100
c => 300
**************************************************************************
Multiple-key map
Maps are a kind of associative containers that stores elements formed by the combination of a key value and a mapped value, much like map containers, but allowing different elements to have the same key value.

Example:
// multimap::begin/end
#include 
#include 
using namespace std;

int main ()
{
  multimap<char,int> mymultimap;
  multimap<char,int>::iterator it;

  mymultimap.insert (pair<char,int>('a',10));
  mymultimap.insert (pair<char,int>('b',20));
  mymultimap.insert (pair<char,int>('b',150));

  // show content:
  for ( it=mymultimap.begin() ; it != mymultimap.end(); it++ )
    cout << (*it).first << " => " << (*it).second << endl;

  return 0;
}


Output:

a => 10
b => 20
b => 150
 ****************************************************************************
Multiple-key set
Multisets are associative containers with the same properties as set containers, but allowing for multiple keys with equal values.

// multiset::begin/end
#include 
#include 
using namespace std;

int main ()
{
  int myints[] = {42,71,71,71,12};
  multiset<int> mymultiset (myints,myints+5);

  multiset<int>::iterator it;

  cout << "mymultiset contains:";
  for ( it=mymultiset.begin() ; it != mymultiset.end(); it++ )
    cout << " " << *it;

  cout << endl;

  return 0;
}

Output
mymultiset contains: 12 42 71 71 71
**********************************************************************************
Priority queue
Priority queues are a type of container adaptors, specifically designed such that its first element is always the greatest of the elements it contains, according to some strict weak ordering condition.

This context is similar to a heap where only the max heap element can be retrieved (the one at the top in the priority queue) and elements can be inserted indefinitely.

The following operations: 
     
    front(),push_back(),pop_back()

// priority_queue::push/pop
#include 
#include 
using namespace std;

int main ()
{
  priority_queue<int> mypq;

  mypq.push(30);
  mypq.push(100);
  mypq.push(25);
  mypq.push(40);

  cout << "Popping out elements...";
  while (!mypq.empty())
  {
     cout << " " << mypq.top();
     mypq.pop();
  }
  cout << endl;

  return 0;
}
 Ouput

Popping out elements... 100 40 30 25
***************************************************************************
FIFO queue
queues are a type of container adaptors, specifically designed to operate in a FIFO context (first-in first-out), where elements are inserted into one end of the container and extracted from the other.

queues are implemented as containers adaptors, which are classes that use an encapsulated object of a specific container class as its underlying container, providing a specific set of member functions to access it elements. Elements are pushed into the "back" of the specific container and popped from its "front".


// queue::push/pop
#include 
#include 
using namespace std;

int main ()
{
  queue<int> myqueue;
  int myint;

  cout << "Please enter some integers (enter 0 to end):\n";

  do {
    cin >> myint;
    myqueue.push (myint);
  } while (myint);

  cout << "myqueue contains: ";
  while (!myqueue.empty())
  {
    cout << " " << myqueue.front();
    myqueue.pop();
  }

  return 0;
}

 
*****************************************************************************
Set
Sets are a kind of associative containers that stores unique elements, and in which the elements themselves are the keys.
// set::begin/end
#include 
#include 
using namespace std;

int main ()
{
  int myints[] = {75,23,65,42,13};
  set<int> myset (myints,myints+5);

  set<int>::iterator it;

  cout << "myset contains:";
  for ( it=myset.begin() ; it != myset.end(); it++ )
    cout << " " << *it;

  cout << endl;

  return 0;
}

 
Output:

myset contains: 13 23 42 65 75
*********************************************************************************
LIFO stack
Stacks are a type of container adaptors, specifically designed to operate in a LIFO context (last-in first-out), where elements are inserted and extracted only from the end of the container.


// stack::push/pop
#include 
#include 
using namespace std;

int main ()
{
  stack<int> mystack;

  for (int i=0; i<5; ++i) mystack.push(i);

  cout << "Popping out elements...";
  while (!mystack.empty())
  {
     cout << " " << mystack.top();
     mystack.pop();
  }
  cout << endl;

  return 0;
}

Output:

Popping out elements... 4 3 2 1 0
******************************************************************************


 
 

 

Thursday, May 13, 2010

Operator overloading

There are two types of operator overloading:

* Unary operator overloading
* Binary operator overloading


Operator overloading is a very important aspect of object-oriented programming. Binary operators can be overloaded in a similar manner as unary operators.
Operator Overloading – Binary Operators

Binary operators, when overloaded, are given new functionality. The function defined for binary operator overloading, as with unary operator overloading, can be member function or friend function.

The difference is in the number of arguments used by the function. In the case of binary operator overloading, when the function is a member function then the number of arguments used by the operator member function is one (see below example). When the function defined for the binary operator overloading is a friend function, then it uses two arguments.

Binary operator overloading, as in unary operator overloading, is performed using a keyword operator.

Binary operator overloading example:
#include
class Exforsys
{
private:
int x;
int y;

public:
Exforsys() //Constructor
{ x=0; y=0; }

void getvalue( ) //Member Function for Inputting Values
{
cout << “\n Enter value for x: “;
cin >> x;
cout << “\n Enter value for y: “;
cin>> y;
}

void displayvalue( ) //Member Function for Outputting Values
{
cout <<”value of x is: “ << x <<”; value of y is: “<}

Exforsys operator +(Exforsys);
};

Exforsys Exforsys :: operator + (Exforsys e2)
//Binary operator overloading for + operator defined
{
int x1 = x+ e2.x;
int y1 = y+e2.y;
return Exforsys(x1,y1);
}

void main( )
{
Exforsys e1,e2,e3; //Objects e1, e2, e3 created
cout<<\n”Enter value for Object e1:”;
e1.getvalue( );
cout<<\n”Enter value for Object e2:”;
e2.getvalue( );
e3= e1+ e2; //Binary Overloaded operator used
cout<< “\nValue of e1 is:”<cout<< “\nValue of e2 is:”<cout<< “\nValue of e3 is:”<}

The output of the above program is:

Enter value for Object e1:
Enter value for x: 10
Enter value for y: 20
Enter value for Object e2:
Enter value for x: 30
Enter value for y: 40
Value of e1 is: value of x is: 10; value of y is: 20
Value of e2 is: value of x is: 30; value of y is: 40
Value of e3 is: value of x is: 40; value of y is: 60


unary operator overloading

#include
using namespace std;

class MyClass {
int x, y, z;
public:
MyClass() {
x = y = z = 0;
}
MyClass(int i, int j, int k) {
x = i;
y = j;
z = k;
}

MyClass operator+(MyClass op2);
MyClass operator=(MyClass op2);
MyClass operator++();

void show() ;
} ;

// Overload +.
MyClass MyClass::operator+(MyClass op2)
{
MyClass temp;

temp.x = x + op2.x; // These are integer additions
temp.y = y + op2.y; // and the + retains is original
temp.z = z + op2.z; // meaning relative to them.
return temp;
}

// Overload assignment.
MyClass MyClass::operator=(MyClass op2)
{
x = op2.x; // These are integer assignments
y = op2.y; // and the = retains its original
z = op2.z; // meaning relative to them.
return *this;
}

// Overload the prefix version of ++.
MyClass MyClass::operator++()
{
x++; // increment x, y, and z
y++;
z++;
return *this;
}

// Show X, Y, Z coordinates.
void MyClass::show()
{
cout << x << ", ";
cout << y << ", ";
cout << z << endl;
}

int main()
{
MyClass a(1, 2, 3), b(10, 10, 10), c;
a.show();
b.show();

c = a + b; // add a and b together
c.show();

c = a + b + c; // add a, b and c together
c.show();

c = b = a; // demonstrate multiple assignment
c.show();
b.show();

++c; // increment c
c.show();

return 0;
}



Functions for both the cases are defined as follows:

a) Pre Increment


Rational operator++()
{
Rational temp;
temp.num = num + den;
temp.den = den;
num = temp.num;
return temp;
}


b) Post Increment


Rational operator++(int dummy)
{
Rational temp;
temp.num = num + den;
temp.den = den;
num = temp.num;
return temp;
}


Static Members

Static means something maintaining state either forever or up to some point. In C++, static members get their life active as soon as the execution of the program starts, no matter, whether they are created in local,
global or class scope.

Following points are to be noted regarding the static members:

* They are allocated as soon as the execution of program starts, regardless of their scope.
* They are de-allocated at the end of the program execution.
* Since they have lifetime, during the whole of the program execution, they retain the values in them.
* They are usable in their scope only though their life is for the whole of the program execution.
* On creation, they are initialized with ZERO.(other locally created variables shall get some undefined (garbage) value in them).


#include
using namespace std;

class Test {

public:
static int objCounter;

Test()
{
Test::objCounter++;
}

~Test()
{
Test::objCounter--;
}
};

int Test::objCounter;

int main(int argc, char * argv[]) {
Test obj1, *ptr, obj2;
cout << endl << "Number of Objects : " << Test::objCounter;
//Will print -> Number of Objects : 2
ptr= new Test;
cout << endl << "Number of Objects : " << Test::objCounter;
//Will print -> Number of Objects : 3
delete ptr;
cout << endl << "Number of Objects : " << Test::objCounter;
//Will print -> Number of Objects : 2
return 0;
}



#include
using namespace std;

class Test {

public:
static int objCounter;

Test()
{
Test::objCounter++;
}

~Test()
{
Test::objCounter--;
}
};

int Test::objCounter;

int main(int argc, char * argv[]) {
Test obj1, *ptr, obj2;
cout << endl << "Number of Objects : " << Test::objCounter;
//Will print -> Number of Objects : 2
ptr= new Test;
cout << endl << "Number of Objects : " << Test::objCounter;
//Will print -> Number of Objects : 3
delete ptr;
cout << endl << "Number of Objects : " << Test::objCounter;
//Will print -> Number of Objects : 2
return 0;
}


Following are the important points specific to CPP:

* Static members of the class must be re-declared outside the class (globally).
* Static data member can be used directly in static member functions only, otherwise they are used using Scope Resolution Operator.
* Static members are created only once as soon as the execution of the program starts and the same is shared among all the objects (obj1, obj2, *ptr) of the class.
* Static members are constrained by the access modifiers (public, private, protected).
* Static functions can only use static data members or local variables, it can not use non static data members of the class.

#include
using namespace std;

class Test1
{
static int testvar;
int testvar1; //non static member
public:
static void testfunc()
{
cout << endl << "Value of static variable : " << testvar;

//Non static members can not be used in static functions.
//cout << endl << "Value of nonstatic variable : " << testvar1;
}
};

int Test1::testvar;

int main(int argc, char *argv[]) {
Test1::testfunc();
return 0;
}




Followers

HomeraDurani

My photo
Rajkot, Gujarat, India
Lecturer in MCA Department Atmiya Institute of Technology & Science Rajkot