PDA

View Full Version : Moving operator overloaded declarations into the class


recluse
10-19-2002, 01:49 PM
From an assignment in class I have this piece of my header file:


class rational
{
public:
rational();
rational(const int &n, const int &d);
int GetNumerator() const;
int GetDenominator() const;
bool SetValues(const int &n, const int &d);

friend ostream & operator<<(ostream &os, const rational r);

//******* COMPARISON OPERATORS *******//
friend bool operator==(const rational &r1, const rational &r2);
friend bool operator!=(const rational &r1, const rational &r2);
friend bool operator<(const rational &r1, const rational &r2);
friend bool operator>(const rational &r1, const rational &r2);
friend bool operator<=(const rational &r1, const rational &r2);
friend bool operator>=(const rational &r1, const rational &r2);

private:
void reduce();
int numerator, denominator;
};
//******* COMPARISON OPERATORS *******//
bool operator==(const rational &r1, const rational &r2);
bool operator!=(const rational &r1, const rational &r2);
bool operator<(const rational &r1, const rational &r2);
bool operator>(const rational &r1, const rational &r2);
bool operator<=(const rational &r1, const rational &r2);
bool operator>=(const rational &r1, const rational &r2);



Notice how there are two declarations for each method? My instructor said that there was a way to make it so there was on inside of the class (before }; is what I'm trying to say) by talking out the first parameter or something. I'm sorry if that was extremely confusing. Does anyone have a clue as to what I'm trying to say?

kmj
10-19-2002, 02:58 PM
dude, no sweat..

unless I'm forgetting something, it's as simple as changing each line inside the function to:

bool operator==(const rational &other);

and removing those declared outside of the class.

This makes the operator overloads become class member functions, you only need one parameter, because the other is the class that is calling it. I.e. the body of the function would look like:

bool rational::operator==(const rational &other)
{
if ((this->numerator == other.numerator )
&& (this->denominator == other.denominator))
{
return true;
}
return false;
}

bwkaz
10-19-2002, 03:53 PM
Some compilers, though, will give you warnings (this-> is old syntax, or something) if you use something like this->numerator. Although it is good for demonstration of stuff like this (and it makes it pretty clear what you're doing), just realize that.

kmj
10-19-2002, 04:03 PM
really? Is it depricated?

bwkaz
10-19-2002, 05:18 PM
The authors of Borland Turbo C++ 2's compiler thought it was... they could obviously be wrong, but that was what it said whenever you did an indirection through "this". I know, I know, it's odd.

I haven't tried using it since then, so I don't know if g++ will warn about it or not.

recluse
10-19-2002, 08:49 PM
What about methods where I return a rational object? Since one's not being passed in per se how do I return it?

kmj
10-19-2002, 11:32 PM
uh.. I'm afraid I don't know what you're asking. Can you be a bit more specific?

bwkaz
10-20-2002, 01:37 AM
You're not ever returning an object of type rational, those are all comparison operators.

Or doesn't that header have all you have to do? If you have to do stuff like the += operator (which adds something to "this", and returns the result), you can do, instead of:

class rational
{
public:
// ...
friend rational& operator+=(rational &r1, const rational &r2);
// ...
};

rational& operator+=(rational &r1, const rational &r2);
, this:

rational& operator+=(const rational &rhs) {
rational temp = rhs; // So we can modify the denominator if necessary

// Convert both denominators to their LCM, and multiply the numerators
// as well -- how to do this is left as an exercise ;-)

this->numerator += temp.numerator;

return *this;
}The important part is the "return *this" part. The rest of it is just finding the least common multiple of the denominators (some people call this the least common denominator, but that's not really what it is, it's the least common multiple of the denominators, i.e., it's a multiple), and converting both fractions so they have equal denominators. Then you add the numerator of the rhs to this's numerator, and return (a reference to) *this.

I was thinking more about this as well, and for any function whose "friend" version's first argument was const, you'll want to declare that function const at the class level as well. For example,

bool rational::operator==(const rational &other) const;For the declaration of kmj's version of ==. The == operator shouldn't ever change either argument, but the only one that's protected is "other", not "this". The const after the argument list makes "this" into a pointer-to-a-const, which protects it.