Five small topics (“digressions”) we have to get out of the way before we do serious operator overloading.
f
occupies very little memory,
and takes only a microsecond to execute.
Bad news:
it takes a microsecond to call
(i.e., go down to)
f
and a microsecond
to return from it
(i.e., come back up).
That means we spend two-thirds of our time on the road.
In a member function, the variable
this
is a pointer that points to the object that the member
function belongs to.
In other words,
it is the invisible pointer that was passed to the member function.
When we passed the object a1
to the function
f
,
we created a copy of the object.
But when we passed the objects
a2
and
a3
to the function f
,
we did not create a copy of the object.
We can do it either way.
The function
f
receives the objects
a2
and
a3
.
f
can change
a2
but not
a3
.
born holding 10 born holding 20 born holding 30 born holding a copy of another object's 10 The function f has been called. dying holding 10 We have returned from the function f. dying holding 30 dying holding 21 dying holding 10
Here is
jsr1
’s
three-file program
height.h
,
height.C
,
main.C
.
The two variables
cm_per_inch
and
inches_per_foot
in the file
height.C
could have been private static data members like the
length
private static data member of the class
date
in
date.h
,
date.C
,
main.C
.
date
which we will provide with overloaded operators:
c++ date.C main.C
<<
take a right operand of class
date
,
date d; cout << d; //If we define operator<< to be a friend function, the computer //would behave as if we'd said //operator<<(cout, d); //If we define operator<< to be a member function, the computer //would behave as if we'd said //cout.operator<<(d); //This would be of no help in allowing operator<< to mention the //private member(s) of d.we have to define a function named
operator<<
.
This function
needs to mention the private member(s) of class
date
.
Therefore this function
must be a member function or a friend of class
date
.
But in C++,
when an operator is implemented as a member function,
it always has to be a member function of its
left
operand.
In this case, the left operand of
<<
is
cout
,
an object of class
ostream
.
Being a member function of the object
cout
would get
the operator<<
function
permission to mention the private member(s) of
cout
,
which we do not need,
but not the private member(s) of the
date
.
Therefore,
operator<<
will have to be a friend of class
date
.
We have to pass
cout
and d
as arguments to the function
operator<<
,
but we don’t want to create copies of these two objects.
We have to let
operator<<
change the value of cout
,
but
we don’t want to let
operator<<
change the value of d
.
Finally, the value of the expression
cout << d
must be
cout
,
so that we can use the expression
cout << d
as part of a larger expression.
cout << d; //operator<<(cout, d); cout << d << "\n"; //operator<<(cout, d) << "\n";
cout << a; // operator<<(cout, a); cout << a << b; // operator<<(operator<<(cout, a), b); cout << a << b << c; //operator<<(operator<<(operator<<(cout, a), b), c); //etc.
+=
take a left operand of class
date
.
//Why the operator += is simpler than the operator + int i {10}; i += 10; //+ merely changes the value of an existing variable. //+ creates a new (invisible) int variable, born holding the value 30. cout << i + 10 << "\n";
The function
operator+=
needs to mention the private members of class
date
.
Therefore it must be either a member function or a friend function of class
date
.
But because it uses the private members of only one object of the class,
we will make it a member function of class date
.
It will be short enough to be an inline function.
The value of the expression
d += 7
must be the new value of d
,
so that we can use the expression
d += 7
as part of a larger expression.
cout << (d += 7) << "\n"; //cout << d.operator+=(7) << "\n";The function
operator+=
must therefore return the
date
object.
We return this
date
object without creating a copy of it.
operator+=
.
They are two different flavors of
operator+
,
and two different flavors of
operator++
.
//in the main function date d; date nextWeek {d + 7}; //date nextWeek {operator+(d, 7)}; date nextYear {365 + d}; //date nextYear {operator+(365, d)}; cout << (d + 7) << "\n"; //cout << operator+(d, 7) << "\n";define the following two inline functions in
date.h
,
after (not inside of!) the declaration for class
date
.
They do not need to be member functions or friends,
because they do not mention any private member of class
date
.
}; //the end of the declaration for class date inline const date operator+(date d, int i) {return d += i;} //JF of P inline const date operator+(int i, date d) {return d += i;} #endif //matches the #ifndef DATE_H at the top of date.hThe above two functions return a
const date
to prevent anyone from saying
date d; //Okay to use the value of an invisible variable (a "temporary"), cout << (d + 7) << "\n"; //Not okay to try to change the value of an invisble variable. (d + 7) += 365;They cannot return a reference to a
date
,
because the object d
created when the function is called is automatically destructed
when the function returns,
and you never want to return a refernce to an object that has already
been destructed.
date
object,
//in the main function date d; cout << d << "\n"; //today ++d; cout << d << "\n"; //tomorrow cout << ++d << "\n"; //the day after tomorrowdefine the following inline function in
date.h
,
after (not inside of!) the declaration for class
date
.
It does not need to be a member function or friend,
because it does not mention any private member of class
date
.
}; //the end of the declaration for class date inline date& operator++(date& d) {return d += 1;} //prefix increment #endif //matches the #ifndef DATE_H at the top of date.h
date
object,
date d; cout << d++ << "\n"; //Outputs today, leaves d holding tomorrow. cout << d << "\n";define the following inline function in
date.h
,
after (not inside of!) the declaration for class
date
.
It does not need to be a member function or friend,
because it does not mention any private member of class date.
The only purpose of the second argument (the int
)
is to allow us to have two functions
with the same name.
That’s why we didn’t even give a name to the second argument.
}; //the end of the declaration for class date inline const date operator++(date& d, int) //postfix increment { const date old {d}; ++d; //d.operator++(); return old; } #endif //matches the #ifndef DATE_H at the top of date.h
-=
,
-
(to subtract an int
from a date
),
prefix --
,
postfix --
.
The
operator-
that takes two objects should be a friend.
Recall that the
operator-
that took an object and an int
was neither a member function nor a friend.
(See the analogous
operator+
in this
date.h
.)
operator==
and
operator<
should be friends.
The four other comparison operators
(operator!=
,
operator<=
,
operator>
,
operator>=
)
should do thir work by calling
operator==
and
operator<
date
.
operator>>
,
like
operator<<
,
should be a friend function.
grade
.
An object of this class can contain one of 14 possible values:
F
,
F+
,
D-
,
D
,
D+
,
C-
,
C
,
C+
,
B-
,
B
,
B+
,
A-
,
A
,
A+
.
Overload all the operators that we just overloaded from class date
.
What data member(s) would an object of class grade
have to contain?
Give it a constructor that takes a string
as its operand.
And give it an operator<<
that will output an uppercase letter, optionally followed by a plus or minus.
grade good {"A"}; grade bad {"C-"}; cout << good << "\n";
myrandom
does only one job: providing a random number.
In other words,
other than the constructor and destructor,
an object of this class has only one member function (rand
)
that we will call.
In this case, we should have named the member function
operator()
.
operator=
.
An
operator=
usually has to do the work of the destructor,
followed by the work of the copy constructor,
checking if we really have two separate objects,
and it must return the object
*this
.
(Digression:
see
string.C
for a string of
char
s
in
"
double
quotes"
.)
operator[]
for an object that holds a series of values.
operator int
for class
grade
.
//Declaration and definition for inline member function in grade.h. operator int() const {return i;}
//Demonstrate operator int in main.C. grade a {"A"}; cout << static_cast<int>(a) << "\n"; //behaves as if you'd written //cout << a.operator int() << "\n";Let's pretend that the class of the object
cin
(namely, class
istream
)
has the following functions.
cin >> i; //operator>>(cin, i); if (cin) { //if (cin.operator bool()) { cout << "The input was successful.\n"; } if (!cin) { //if (cin.operator!()) { cout << "The input was not successful.\n"; }