Friend Functions and Operator Overloading

Here is a program in which we compare the birthdates of two people. Simple Then we added a few things. A Journey to understanding and implementation of a class

In the past several class sections we went through several examples of classes.  In particular we carried out several programs in which we used class Money.  Let's summarize some of the things we did.

First I show you a program that asks users to input the amount of money for two people.  The money for each person is entered in two parts, the dollars part and the cents part.  The program then displays each money and also sums them up and will display the result.  We use a couple function, one for display purpose and the other to compute the sum.

// Program plain_money.C
// Rahman Tashakkori - CS1440-410
// A program that asks for your_money and my_money and then displays them
// and, also displays their sum.  In this program a money is made up two
// parts: the dollars part and the cents part both as integers.

#include <iostream>
using namespace std;

void display_money(int d, int c);
void add(int y_d, int y_c, int m_d, int m_c, int& s_d, int& s_c);

int main( )
{
    int my_money_d, my_money_c;      // The dollars and cents for my money
    int your_money_d, your_money_c;  // The dollars and cents for your money
    int sum_money_d, sum_money_c;      // The dollars and cents for the sum

    cout << "Enter the dollar part of your money ";
    cin >> your_money_d;
    cout << endl;
    cout << "Enter the cent part of your money ";
    cin >> your_money_c;
    cout << endl;
    display_money(your_money_d,your_money_c);

    cout << "Enter the dollar part of my money ";
    cin >> my_money_d;
    cout << endl;
    cout << "Enter the cent part of my money ";
    cin >> my_money_c;
    cout << endl;
    display_money(my_money_d, my_money_c);

    add(your_money_d, your_money_c, my_money_d, my_money_c, sum_money_d, sum_mon
    cout << "The sum was: ";
    display_money(sum_money_d, sum_money_c);

    return 0;
}

void display_money(int d, int c)
{
    cout << "$" << d << ".";
    if(c < 10)
        cout << "0";
    cout << c << endl;
    return;
}

void add(int y_d, int y_c, int m_d, int m_c, int& s_d, int& s_c)
{
    s_d = y_d + m_d;         //Sum the dollars up

    s_c = y_c + m_c;         //Sum the cents up

    s_d = s_d + s_c/100;  //if cents > 100, add 1 to dollars for
                                      // each 100 cents

     s_c = s_c%100; // count for those cents that are converted to dollars
}

Struct
Okay, the above program worked.  But, it seems like a great idea, if we could somehow define a variable of type money that keeps both the dollars and cents part of each money.  No, not like a double value, we still want to have the dollars and cents parts separately. We can use struct or a class to do so.  Below is the above code written using a struct.

// Program money_with_struct.C
// Rahman Tashakkori - CS1440-410
// A program that asks for your_money and my_money and then displays them
// and, also displays their sum.  In this program a money is made up two
// parts: the dollars part and the cents part both as integers.

#include <iostream>
using namespace std;

struct Money
{
    int dollars;
    int cents;
};

void display_money(Money m);

// This is one way of doing this.
void add(Money m1, Money m2, Money& m);

int main( )
{
    //Pay attention here
    Money my_money, your_money, sum_money;

    cout << "Enter the dollar part of your money ";
    cin >> your_money.dollars;
    cout << endl;
    cout << "Enter the cent part of your money ";
    cin >> your_money.cents;
    cout << endl;
    display_money(your_money);

    cout << "Enter the dollar part of my money ";
    cin >> my_money.dollars;
    cout << endl;
    cout << "Enter the cent part of my money ";
    cin >> my_money.cents;
    cout << endl;
    display_money(my_money);

    add(your_money, my_money, sum_money);
    cout << "The sum was: ";
    display_money(sum_money);

    return 0;
}

void display_money(Money m)
{
    cout << "$" << m.dollars << ".";
    if(m.cents < 10)
        cout << "0";
    cout << m.cents << endl;
    return;
}

void add(Money y, Money m, Money& s)
{
    s.dollars = y.dollars + m.dollars; //Sum the dollars up

    s.cents = y.cents + m.cents; //Sum the cents up

    s.dollars = s.dollars + s.cents/100;  //if cents > 100, add 1 to dollars for
                                                          // each 100 cents
    s.cents = s.cents%100; // count for those cents that are converted to dollars
}

Classes
So we used (struct) a new data type (struct) to bundle the dollars and the cents of each money together as one but, we were able to access each part using the "." operator.  Notice that we have accessed the dollars part of my_money in the main using my_money.dollars, and we also access it in the display and add functions in a similar way.  Similar thing is true for the cents part.

Now let's get a bit fancier.  We can write the program using classes.

A class with a set function
// Program money_with_class1.C
// Rahman Tashakkori - CS1440-410
// A program that asks for your_money and my_money and then displays them
// and, also displays their sum.  In this program a money is made up two
// parts: the dollars part and the cents part both as integers.

#include <iostream>
using namespace std;

//Pay attention here
class Money
{
  public:
    void set(int d, int c);
    void display_money();
    // This is one way of doing this.
    void add(Money m1, Money m2);
  private:
    int dollars;
    int cents;
};

int main( )
{
    Money my_money, your_money, sum_money;

    //Pay attention here
    int d, c;

    cout << "Enter the dollar part of your money ";
    cin >> d;
    cout << endl;
    cout << "Enter the cent part of your money ";
    cin >> c;
    cout << endl;

    //Pay attention here
    your_money.set(d, c);
    your_money.display_money();

    cout << "Enter the dollar part of my money ";
    cin >> d;
    cout << endl;
    cout << "Enter the cent part of my money ";
    cin >> c;
    cout << endl;

    my_money.set(d, c);
    my_money.display_money();

    sum_money.add(your_money, my_money);
    cout << "The sum was: ";
    sum_money.display_money();

    return 0;
}

//Pay attention here, a new functions that sets
//the dollars and cents to the values that are
//passed to it as arguments
void Money::set(int d, int c)
{
    dollars = d;
    cents = c;
}

//Pay attention here, adding scope resolution ::
void Money::display_money()
{

    //Pay attention here, no need for . operator here
    cout << "$" << dollars << ".";
    if(cents < 10)
        cout << "0";
    cout << cents << endl;
    return;
}

void Money::add(Money y, Money m)
{
    dollars = y.dollars + m.dollars; //Sum the dollars up

    cents = y.cents + m.cents; //Sum the cents up

    dollars = dollars + cents/100;  //if cents > 100, add 1 to dollars for
                                                  // each 100 cents
    cents = cents%100; // count for those cents that are converted to dollars
}

Let's have a quick look at the above program.  Here is the highlights:

Class with constructors
// Program money_with_constructor.C
// Rahman Tashakkori - CS1440-410
// A program that asks for your_money and my_money and then displays them
// and, also display their sum.  In this program a money is made up two
// parts: the dollars part and the cents part both as integers.

#include <iostream>
using namespace std;

//Pay attention here
class Money
{
  public:
    //Pay attention here, we replaced the set function with constructors
    Money();
    Money(int d, int c);
    void display_money();
    // This is one way of doing this.
    void add(Money m1, Money m2);
  private:
    int dollars;
    int cents;
};

int main( )
{
    Money my_money, your_money, sum_money;

    //Pay attention here
    int d, c;

    cout << "Enter the dollar part of your money ";
    cin >> d;
    cout << endl;
    cout << "Enter the cent part of your money ";
    cin >> c;
    cout << endl;

    //Pay attention here, now with constructor we use =
    //instead of the .
    your_money = Money(d, c);
    your_money.display_money();

    cout << "Enter the dollar part of my money ";
    cin >> d;
    cout << endl;
    cout << "Enter the cent part of my money ";

    cin >> c;
    cout << endl;

    my_money = Money(d, c);
    my_money.display_money();

    sum_money.add(your_money, my_money);
    cout << "The sum was: ";
    sum_money.display_money();

    return 0;
}

Money::Money()
{
     //This one does not do anything for now
}

//Pay attention here, a new functions that sets
//the dollars and cents to the values that are
//passed to it as arguments
Money::Money(int d, int c)
{
    dollars = d;
    cents = c;
}

//Pay attention here, adding scope resolution ::
void Money::display_money()
{

    //Pay attention here, no need for . operator here
    cout << "$" << dollars << ".";
    if(cents < 10)
        cout << "0";
    cout << cents << endl;
    return;
}

void Money::add(Money y, Money m)
{
    dollars = y.dollars + m.dollars; //Sum the dollars up

    cents = y.cents + m.cents; //Sum the cents up

    dollars = dollars + cents/100;  //if cents > 100, add 1 to dollars for
                                                          // each 100 cents
    cents = cents%100; // count for those cents that are converted to dollars
}

Multiple Files
One last thing and we will be done.  In the above program, we used a class.  We can leave the class (heading) definition in one file, all the functions in one file, and the main in another one but make sure we see everything as before.  Here is what we will do.

// money.h file
#ifndef MONEY_H
 #define MONEY_H

class Money
{
  public:
    //Pay attention here, we replaced the set function with constructors
    Money();
    Money(int d, int c);
    void display_money();
    // This is one way of doing this.
    void add(Money m1, Money m2);
  private:
    int dollars;
    int cents;
};
#endif

// money.C file

#include <iostream>
#include "money.h"
using namespace std;

Money::Money()
{
     //This one does not do anything for now
}

//Pay attention here, a new functions that sets
//the dollars and cents to the values that are
//passed to it as arguments
Money::Money(int d, int c)
{
    dollars = d;
    cents = c;
}

//Pay attention here, adding scope resolution ::
void Money::display_money()
{

    //Pay attention here, no need for . operator here
    cout << "$" << dollars << ".";
    if(cents < 10)
        cout << "0";
    cout << cents << endl;
    return;
}

void Money::add(Money y, Money m)
{
    dollars = y.dollars + m.dollars; //Sum the dollars up

    cents = y.cents + m.cents; //Sum the cents up

    dollars = dollars + cents/100;  //if cents > 100, add 1 to dollars for
                                                          // each 100 cents
    cents = cents%100; // count for those cents that are converted to dollars
}

// The main program - my_program.C
#include <iostream>
#include "money.h"

using namespace std;

int main( )
{
    Money my_money, your_money, sum_money;

    //Pay attention here
    int d, c;

    cout << "Enter the dollar part of your money ";
    cin >> d;
    cout << endl;
    cout << "Enter the cent part of your money ";
    cin >> c;
    cout << endl;

    //Pay attention here, now with constructor we use =
    //instead of the .
    your_money = Money(d, c);
    your_money.display_money();

    cout << "Enter the dollar part of my money ";
    cin >> d;
    cout << endl;
    cout << "Enter the cent part of my money ";

    cin >> c;
    cout << endl;

    my_money = Money(d, c);
    my_money.display_money();

    sum_money.add(your_money, my_money);
    cout << "The sum was: ";
    sum_money.display_money();

    return 0;
}

Now you can compile the program in a different way, but the program works the same.

% g++ my_program.C  money.C