Object Oriented Programming

In object oriented programming we can create objects such as a ball that has properties such as position, size, color and behaviors such as fall, roll and bounce.  The ability to create objects means allows us to create programs that more closely resemble the real world.  Such programs are easier to design and maintain, particularly in large software projects.  In C++ we can create our own data types such as ball using the keyword class.  A class contains data members such as position, size and color and function members such as fall, roll and bounce.  The data and the methods are bound together as a single unit.  The class forms a blueprint from which objects can be created.  An object is an instance of a class.  Many objects can be created from the same class in the same way that many cookies can be made from the same cookie cutter.  The three fundamental characteristics of object oriented programming are

Encapsulation

Encapsulation refers to the process of binding the data and the methods that work with the data together into a class.  The details of how the methods are implemented are hidden from the user of the class.  Typically, the user of a class must use the member functions to change the values of the data members in the class.  This helps prevent accidentally changing the values of the data which can be a difficult problem to detect and fix in a large software project. 

Declaring classes

In the class declaration we choose the data members and functions to be included in the class.  A class declaration has four main parts.

Implementing classes

In this section we study some common member functions.

Example: Employee class.

# include<iostream>
# include<string>
using namespace std;

class Employee { private:     string firstName;     string lastName;     long id; public:     Employee( );     Employee(string, string, long);     void setEmployeeData(string, string, long);     void printEmployee( ); };

Employee::Employee( ) {     firstName = "";     lastName = "";     id = 0; }

Employee::Employee(string first, string last, long number) {     firstName = first;     lastName = last;     id = number; }

void Employee::setEmployeeData(string first, string last, long number)
{     firstName = first;     lastName = last;     id = number; }

void Employee::printEmployee( ) {     cout << "First name : " << firstName << endl;     cout << "Last name : " << lastName << endl;     cout << "Employee id: " << id << endl; }

int main( ) {     // single employee
    Employee teacher("Kim","Ward",9134);     cout << "CREATE A SINGLE EMPLOYEE." << endl;     teacher.printEmployee( );
    // entire staff
    Employee staff[4];     cout << "CREATE AN ENTIRE STAFF." << endl;     staff[0].setEmployeeData("John", "Smith", 4356);     staff[1].setEmployeeData("Judy", "Adams", 6787);     staff[2].setEmployeeData("Sam", "Spud", 6534);     staff[3].setEmployeeData("Sandy", "Web", 9812);     for (int i=0; i<4; i++)     staff[i].printEmployee( );
    return 0; }

Inheritance

Inheritance allows us to create new classes from existing classes.  The original class is called the base class.  The new class is called the derived class.  The derived class inherits the data and function members from the base class and adds additional data and function members.  A programmer can often find a class that is close to meeting her needs and then add some additional data or functions.  The programmer does not need to be concerned with the implementation details of the base class and is free to focus only on the derived class.  Using previously developed classes is an excellent form of software reuse (no need to reinvent the wheel).   A base class such as mammal can be used to derive many classes such as cat, dog, horse and bear.  The properties and behaviors common to all mammals should be placed in the base class and the remaining more specific properties and behaviors are distributed amongst the derived classes.

# include<iostream>
# include<string>
using namespace std;

class Employee
{
private:
    string firstName;
    string lastName;
    long id;
public:
    Employee( );
    Employee(string, string, long);
    void setEmployeeData(string, string, long);
    void printEmployee( );
};

Employee::Employee( )
{
    firstName = "";
    lastName = "";
    id = 0;
}

Employee::Employee(string first, string last, long number)
{
    firstName = first;
    lastName = last;
    id = number;
}

void Employee::setEmployeeData(string first, string last, long number)
{
    firstName = first;
    lastName = last;
    id = number;
}

void Employee::printEmployee( )
{
    cout << "First name : " << firstName << endl;
    cout << "Last name : " << lastName << endl;
    cout << "Employee id: " << id << endl;
}

class Boss : public Employee
{
private:
    double salary;
    double bonus;
public:
    Boss(string, string, long, double, double);
    double earnings( );
    void printBoss( );
};

Boss::Boss(string first, string last, long id, double s, double b) : Employee(first, last, id)
{
    salary = s;
    bonus = b;
}

double Boss::earnings( )
{
    return salary + bonus;
}

void Boss::printBoss( )
{
    Employee::printEmployee( );
    cout << "Salary : " << salary << endl;
    cout << "Bonus : " << bonus << endl;
}

int main( )
{
    Boss factory("Sugar", "Spice", 1345, 50000.0, 1000.0);
    cout << "CREATE A BOSS FROM AN EMPLOYEE." << endl;
    factory.printBoss( );

    return 0;
}

Polymorphism

Polymorphism refers to the ability to associate many meanings with one function name using dynamic binding.  For example in the program below the base class Employee has a print( ) method and the derived classes Boss and HourlyWorker both have print( ) methods.  The decision as to which of the print( ) methods is to be executed is made at run time.

# include<iostream>
# include<string>
using namespace std;

// Employee is an abstract class since it contains a pure virtual function.
// An abstract class can only be used as a base class for deriving other
// classes. One cannot create objects of an abstract class, since it is
// not a complete class definition.

class Employee
{
private:
    string firstName;
    string lastName;
    long id;
public:
    Employee( );
    Employee(string, string, long);
    void setEmployeeData(string, string, long);
    virtual void print( ); // virtual function
    virtual double earnings( ) = 0; // pure virtual function
};

Employee::Employee(string first, string last, long number)
{
    firstName = first;
    lastName = last;
    id = number;
}

void Employee::setEmployeeData(string first, string last, long number)
{
    firstName = first;
    lastName = last;
    id = number;
}

void Employee::print( )
{
    cout << "First name : " << firstName << endl;
    cout << "Last name : " << lastName << endl;
    cout << "Employee id: " << id << endl;
}

// Boss is a derived class

class Boss : public Employee
{
private:
    double salary;
    double bonus;
public:
    Boss(string, string, long, double, double);
    double earnings( );
    void print( );
};

Boss::Boss(string first, string last, long id, double s, double b) : Employee(first, last, id)
{
    salary = s;
    bonus = b;
}

double Boss::earnings( )
{
    return salary + bonus;
}

void Boss::print( )
{
    Employee::print( );
    cout << "Salary : " << salary << endl;
    cout << "Bonus : " << bonus << endl;
}

// HourlyWorker is a derived class

class HourlyWorker : public Employee
{
private:
    double hours;
    double wage;
public:
    HourlyWorker(string, string, long, double, double);
    double earnings( );
    void print( );
};

HourlyWorker::HourlyWorker(string first, string last, long id, double h, double w) : Employee(first, last, id)
{
    hours = h;
    wage = w;
}

double HourlyWorker::earnings( )
{
    return hours*wage;
}

void HourlyWorker::print( )
{
    Employee::print( );
    cout << "Hours : " << hours << endl;
    cout << "Wage : " << wage << endl;
}

// Polymorphism involves dynamic binding or waiting until run time to determine
// which implementations of the print( ) and earning( ) method to use.

int main( )
{
    // boss

    Boss factory("Sugar", "Spice", 1345, 50000.0, 1000.0);
    cout << "CREATE A BOSS FROM AN EMPLOYEE." << endl;
    factory.print( );
    cout << "factory boss earns $" << factory.earnings( ) << endl;

    // hourly worker

    HourlyWorker good("James", "Henry", 6764, 40, 20);
    cout << "CREATE AN HOURLY WORKER FROM AN EMPLOYEE." << endl;
    good.print( );
    cout << "good hourly worker earns $" << good.earnings( ) << endl;

    return 0;
}