Lab 4 - part 2 - Friend Functions
back to part 1     on to part 3

So far, you have learned to define a class and to use member functions of the class to access the private member variables of that class.  Previously, we mentioned that a private member variable of a class could be accessed by a member function. However, that is not the only way to access a private member variable.   A function can be made a friend of a class, and thus, can be given the authority to access the private member variables of that class.  In such a case, the friend function is not a class member and can be used throughout the program as an independent function.  A friend function can not only access the private member variables, but it can also change them.  One may find it tempting to define all functions used in a program as friends of all classes in that program, so there would be no need for accessor or mutator functions.  Although in theory this may be true, it is not practical.  I am sure you can think of several good reasons for not defining all functions as friend of all classes.

In the following program, we will use a class AltMoney to add two dollar amounts.  The class is defined with a member function add that adds the dollars and cents amounts for the two inputs.  Please note that the AltMoney class presented in this lab is a much simpler version of the one in Display 8.3 of the textbook.

// P81.cpp - This program adds two different people's amounts
#include<iostream>
#include<cstdlib>
using namespace std;

class AltMoney
{
    public:
        AltMoney();
        AltMoney(int d, int c);

        void add(AltMoney m1, AltMoney m2);
        void display_money( );
    private:
        int dollars;
        int cents;
};

void read_money(int& d, int& c);

int main( )
{
     int d, c;
     AltMoney m1, m2, sum;

     sum = AltMoney(0,0);

     read_money(d, c);
     m1 = AltMoney(d,c);
     cout << "The first amount is:";
     m1.display_money();

     read_money(d, c);
     m2 = AltMoney(d,c);
     cout << "The second amount is:";
     m2.display_money();

     sum.add(m1,m2);
     cout << "The sum is:";
     sum.display_money();

     return 0;
}

AltMoney::AltMoney()
{
}

AltMoney::AltMoney(int d, int c)
{
       dollars = d;
       cents = c;
}

void AltMoney::display_money()
{
     cout << "$" << dollars << "." << cents << endl;
}

void AltMoney::add(AltMoney m1, AltMoney m2)
{
     int extra = 0;
     cents = m1.cents + m2.cents;
     if(cents >=100){
         cents = cents - 100;
         extra = 1;
     }

     dollars = m1.dollars + m2.dollars + extra;
}

void read_money(int& d, int& c)
{
     cout << "Enter dollar \n";
     cin >> d;
     cout << "Enter cents \n";
     cin >> c;
     if( d < 0 || c < 0)
     {
            cout << "Invalid dollars and cents, negative values\n";
            exit(1);
      }
}

As defined here, all functions are members of class AltMoney, except for read_money().
But suppose we were to define the add function as:

void add(AltMoney m1, AltMoney m2)
{
     int extra = 0;
     cents = m1.cents + m2.cents;
     if(cents >=100){
         cents = cents - 100;
         extra = 1;
     }

     dollars = m1.dollars + m2.dollars + extra;
}

As you may have noticed, based on this definition, function add is not a member function any more, meaning that add can no longer access the dollars and cents variables of m1 and m2.  In fact, if you try the program like this, without making any change, you will get several syntax errors.  In order to give add (in its new definition) the authority to access the private member variables, we will make it a friend of class AltMoney.

Here is the new version of P81.cpp program with add as a friend function.

// P81a.cpp - This program adds amount of two different people
#include<iostream>
#include<cstdlib>
using namespace std;

class AltMoney
{
    public:
        AltMoney();
        AltMoney(int d, int c);

        friend void add(AltMoney m1, AltMoney m2, AltMoney& sum);
        void display_money( );
    private:
        int dollars;
        int cents;
};

void read_money(int& d, int& c);

int main( )
{
     int d, c;
     AltMoney m1, m2, sum;

     sum = AltMoney(0,0);

     read_money(d, c);
     m1 = AltMoney(d,c);
     cout << "The first amount is:";
     m1.display_money();

     read_money(d, c);
     m2 = AltMoney(d,c);
     cout << "The second amount is:";
     m2.display_money();

     add(m1,m2, sum);
     cout << "The sum is:";
     sum.display_money();

     return 0;
}

AltMoney::AltMoney()
{
}

AltMoney::AltMoney(int d, int c)
{
       dollars = d;
       cents = c;
}

void AltMoney::display_money()
{
     cout << "$" << dollars << ".";
     if(cents <= 9)
         cout << "0";  //to display a 0 in the left for numbers less than 10
     cout << cents << endl;
}

void add(AltMoney m1, AltMoney m2, AltMoney& sum)
{
     int extra = 0;
     sum.cents = m1.cents + m2.cents;
     if(sum.cents >=100){
         sum.cents = sum.cents - 100;
         extra = 1;
      }
      sum.dollars = m1.dollars + m2.dollars + extra;
}

void read_money(int& d, int& c)
{
     cout << "Enter dollar \n";
     cin >> d;
     cout << "Enter cents \n";
     cin >> c;
     if( d < 0 || c < 0)
     {
            cout << "Invalid dollars and cents, negative values\n";
            exit(1);
      }
}

In this program the function add is no longer a member function, but it is a friend to the class AltMoney and has access to private member variables.  In general, we may want to include the function that does the reading of variables as a function member or make it a friend so that it reads the dollars and cents and directly assigns them to the dollars and cents of an object.

Exercise 8.1
Modify the above program to include the following changes.  Call your new program ex1.cpp.
            1) make function add of type AltMoney.  Thus, this function now computes the sum of dollars and cents and returns it as AltMoney.  Note that in the above version of the program, you have passed the object sum as call_by_reference.
            2) add a new friend function, subtract, that computes the subtraction of one amount from the other.
            3) Make read_money a member function.  Note that if you make read_money a member function, then you can use it to directly initialize the dollars and cents of an AltMoney type object directly.


back to part 1     on to part 3