* Example, let's say we would like to compare two Jar_Type objects for equality.
class Jar_Type {
public:
...
Boolean equal(const Jar_Type& other) const;
...
private:
int units;
};
* The function compares a Jar_Type object with another.
Jar_Type jar1, jar2;
if (jar1.equal(jar2)) { ... }
// in the .cpp file...
Boolean Jar_Type::equal(const Jar_Type& other) const
{ return (units == other.units);
}
* The client cannot write:
if (equal(jar1, jar2)) { ...
* That would require equal function to be a global function.
Boolean equal(const Jar_Type& jar1,
const Jar_Type& jar2)
{
return (jar1.quantity() == jar2.quantity());
}
* A class may grant permission to non-member functions to access its private members!
class Jar_Type {
public:
friend Boolean equal(const Jar_Type& jar1,
const Jar_Type& jar2);
...
};
* A friend can access the private member "units"!
Boolean equal(......)
{
return (jar1.units == jar2.units);
}
* There is really no need to make the non member function a friend since we can do without it. But we will see examples where it would really come in handy shortly.
* Just like the real life, friends are dangerous! Use them with extra caution!
* In addition to treat a function a friend, you can treat a whole class a friend too!
class A {
friend class B;
...
};
* Now any B's members can access A's private members! Use it with extra extra caution!
Operator overloading
* Normally, the only operators defined for C++ classes are (?) and (?). (page 144).
* However, the programmer can overload many operators to apply to class instances.
* It would really be nice if we can compare two Jar_Type instances using "=="!
class Jar_Type {
public:
Boolean operator == (const Jar_Type& other) const;
};
Jar_Type jar1, jar2;
...
if (jar1 == jar2) {
...
}
* Another example of operator overloading (very common!)
class Jar_Type {
public:
friend ostream& operator << (ostream& ost,
const Jar_Type& jar);
...
};
ostream& operator << (......) {
ost << "I have " << jar.units << " units!\n";
return ost;
}
A Study in Design
#ifndef FRACTION_H
#define FRACTION_H
#include "bool.h" // if not using Mac/Symantec
#include <iostream.h> // why need this?
class Fraction {
public:
Fraction(int in_num, int in_den = 1);
friend ostream& operator << (ostream& ost,
const Fraction& frac);
void simplify();
Fraction operator* (const Fraction& other) const;
Boolean operator== (const Fraction& other) const;
private:
int numerator;
int denominator;
};
#endif
// fraction.cpp
#include "fraction.h"
Fraction::Fraction(int in_num, int in_den)
{
numerator = in_num;
denominator = in_den;
simplify(); // your text forgets to do this!
}
ostream&
operator << (ostream& ost, const Fraction& frac)
{
ost << frac.numerator << "/" << frac.denominator;
return ost;
}
Fraction
Fraction::operator * (const Fraction& other) const
{
Fraction result(numerator * other.numerator,
denominator * other.denominator);
result.simplify();
return result;
}
Boolean
Fraction::operator == (const Fraction& other) const
{
return ((numerator == other.numerator)
&& (denominator == other.denominator));
}
* Note we make sure that a Fraction instance is always simplified so "==" is written that way!
Summary
* Modules and classes are both units of modularity.
* A module is an organization mechanism (may or may not have classes).
* A class is a C++ construct to create ADTs.
* A class is a type.
* The "private" keyword can be used to hide information from the clients.
* Usually, we hide all data members. (why?)
* Usually, we expose many member functions. (why?)