Public and Private Members

  1. When defining a class, the normal practice is to make all member variable private. This imposes severe restrictions that requires more effort from the programmer, but has the advantage of making the code easier to understand and easier to modify in the future.

  2. More effort is needed to deal with private member variables since the only way to access them is through the member functions of the class.

  3. In general one needs to retrieve the value stored in a variable and to set it value.

  4. A complete set of member function must therefore be introduced to retrieve or access the values of private member variables. These member functions are called accessor functions.

  5. In addition, member functions must be introduced to set the values of private member variables.

  6. A private member function can be used in the definition of any other member function within the same class, but no where else. They are used in the definition of other member functions.

  7. The DayOfYear class is rewritten so that its member variables are private. All its member functions are public. A member function "set" can be used to set the values of the month and day. A member function "input" allows these values to be input from the keyboard. These values can be retrieved using the member functions "get_month" and "get_day", or output to the screen using the member function "output".

  8. //A better version of the DayOfYear class.
    #include <iostream>

    class DayOfYear
    {
    public:
        void input( );
        void output( );

        void set(int new_month, int new_day);
        //Precondition: new_month and new_day form a possible date.
        //Postcondition: The date is reset according to the arguments.

        int get_month( );
        //Returns the month, 1 for January, 2 for February, etc.

        int get_day( );
        //Returns the day of the month.
    private:
        int month;
        int day;
    };

    int main( )
    {
        DayOfYear today, bach_birthday;
        cout << "Enter today's date:\n";
        today.input( );
        cout << "Today's date is ";
        today.output( );

        bach_birthday.set(3, 21);
        cout << "J. S. Bach's birthday is ";
        bach_birthday.output( );

        if ( today.get_month( ) == bach_birthday.get_month( ) &&
           today.get_day( ) == bach_birthday.get_day( ) )
           cout << "Happy Birthday Johann Sebastian!\n";
        else
           cout << "Happy Unbirthday Johann Sebastian!\n";
        return 0;
    }

    //Uses iostream
    void DayOfYear::input( )
    {
        cout << "Enter the month as a number: ";
        cin >> month;
        cout << "Enter the day of the month: ";
        cin >> day;
    }


    //Uses iostream
    void DayOfYear::output( )
    {
        cout << "month = " << month << ", day = " << day << endl;
    }

    void DayOfYear::set(int new_month, int new_day)
    {
        month = new_month;
        day = new_day;
    }

    int DayOfYear::get_month( )
    {
        return month;
    }

    int DayOfYear::get_day( )
    {
        return day;
    }

  9. Members listed at the start of a class definition without specifying either public or private are assumed private members. However it is good to explicitly label each group of members as either public or private.

    The assignment operator = can be used with structures or objects of a class. Suppose the objects due-date and tomorrow are declared as follows:

    DayOfYear due_date, tomorrow;

    and tomorrow.month and tomorrow.day have been assigned values, then the assignment statement:

    due_date = tomorrow;

    is equivalent to the following assignment statements:

    due_date.month = tomorrow.month;
    due_date.day = tomorrow.day;

    even though month and day are private member variables of the DayOfYear class.

  10. The following Bank Account class has a private function "fraction", that takes one argument that is an interest rate expressed as a percentage and converts it to a fraction.

  11. //Program to demonstrates the class BankAccount.
    #include <iostream>

    //Class for a bank account:
    class BankAccount
    {
    public:
        void set(int dollars, int cents, double rate);
        //Postcondition: The account balance has been set to $dollars.cents;
        //The interest rate has been set to rate percent.

        void set(int dollars, double rate);
        //Postcondition: The account balance has been set to $dollars.00.
        //The interest rate has been set to rate percent.

        void update( );
        //Postcondition: One year of simple interest has been
        //added to the account balance.

        double get_balance( );
        //Returns the current account balance.

        double get_rate( );
        //Returns the current account interest rate as a percent.

        void output(ostream& outs);
        //Precondition: If outs is a file output stream, then
        //outs has already been connected to a file.
        //Postcondition: Account balance and interest rate have
        //been written to the stream outs.
    private:
        double balance;
        double interest_rate;

        double fraction(double percent);
        //Converts a percent to a fraction.
        //For example, fraction(50.3) returns 0.503.
    };

    int main( )
    {
        BankAccount account1, account2;
        cout << "Start of Test:\n";

        account1.set(123, 99, 3.0);
        cout << "account1 initial statement:\n";
        account1.output(cout);

        account1.set(100, 5.0);
        cout << "account1 with new setup:\n";
        account1.output(cout);

        account1.update( );
        cout << "account1 after update:\n";
        account1.output(cout);

        account2 = account1;
        cout << "account2:\n";
        account2.output(cout);
        return 0;
    }

    void BankAccount::set(int dollars, int cents, double rate)
    {
        balance = dollars + 0.01*cents;
        interest_rate = rate;
    }

    void BankAccount::set(int dollars, double rate)
    {
        balance = dollars;
        interest_rate = rate;
    }

    void BankAccount::update( )
    {
        balance = balance + fraction(interest_rate)*balance;
    }

    double BankAccount::fraction(double percent)
    {
        return (percent/100.0);
    }

    double BankAccount::get_balance( )
    {
        return balance;
    }

    double BankAccount::get_rate( )
    {
        return interest_rate;
    }

    //Uses iostream:
    void BankAccount::output(ostream& outs)
    {
        outs.setf(ios::fixed);
        outs.setf(ios::showpoint);
        outs.precision(2);
        outs << "Account balance $" << balance << endl;
        outs << "Interest rate " << interest_rate << "%" << endl;
    }

  12. Note that the member function "output" take a formal parameter of type ostream so that it can be called with an argument that is either the standard output stream cout or a file output stream. Therefore if fout has been declared as a file output stream and has been connected to an external file, then the following would write the data stored in the object account1 to this file:

    account1.output(fout);

    The same data can be sent to the screen instead if the above code is replaced by:

    account1.output(cout);