Friend Functions

Sometimes accessor functions are awkward or inefficient:

Consider function equal(), which is used to determine whether two Account
objects represent the same Account. (We are using "equal" instead of "==".)

class Account {

public:

  float getBalance() const;

private:

  float balance;

}

float Account::getBlance() const {

  return balance;

}

// equal is not a member of the class

bool equal(  const Acount& act1,

             const Account& act2) const

{

    return (act1.getBalance() == act2.getBalance());

}

Since "balance" is private and equal() is not a member of the class

          we have the overhead of two function calls.  

If it were legal, it would be much more efficient to do this:

bool equal(  const Acount& act1,

             const Account& act2) const

{

    return (act1.balance == act2.balance);

}

The class Account can grant this privilege to function equal.

To grant access to private class members, Account
can declare selected functions to be "friend" of the class:

class Account {

public:

  friend bool equal(const Acount& act1,

                    const Account& act2) const;

  float getBalance() const;

private:

  float balance;

}

// equal is still not a member of the class!!

// but it has "special status"

bool equal(   const Acount& act1,

          const Account& act2) const

{

  return (act1.balance == act2.balance);

}

Note:

          - The word "friend" appears only in a class which wants to grant

                   special access -- it isn't part of the prototype or definition.

          - We do not use Accout::equal(..) since equal is not a member of Account.
          - We do not use the dot operator to call equal since it isn't a member
                   of account.

Equal is used like this:

     if (equal(act1,act2)) ...

For a non-member function like equal(), it is your choice whether to
make equal() a friend of the class.


Slide 3

Friend Functions vs Member Functions

Why not make equal a member of the class?

  class Account

  public:

     bool equal(const Account& act1) const;

     ...

  }

  bool Account::equal(const Account& act1) const {

     return (balance == act1.balance);

  }

Then if act1 and act2 are accounts, equal would be used like this:

  if (act1.equal(act2))

or                     

  if (act2.equal(act1))

This is ok, but it is awkward. It is an arbitrary choice which object is the
calling object and which object is the parameter. So it doesn't "feel" right.

 

Instead, if we make equal() a non-member funtion, we treat

both objects the same:

     if (equal(act1,act2)) ...

If equal() is a non-member function, then we must choose whether or not
to make it a friend of the class.

Next: Overloading Operators


Slide 4