2

I've been making a fraction class recently, I'm not getting the intended results when overloading the operators, and I'm not sure why. Hoping someone can help shed some light. I've tried to only include the relevant code.

const fraction fraction::operator* (fraction frac)
{
    return fraction(frac.numerator * numerator, frac.denominator * denominator);
}

const fraction fraction::operator* (int num)
{
    return fraction(numerator*num, denominator);
}

fraction& fraction::operator= (const fraction &rightSide)
{
    return *this;
}

These operations are the ones I found to be working correctly (where frac# is a fraction object):

frac1 = frac2;
frac3 = frac4 * 2;
frac5 = frac6 * frac7;

The above operations work as expected, but the following operation leaves frac8 just as it was initialized:

fraction frac8(4, 5); // Initializes a fraction, setting numerator = 4, denominator = 5
frac8 = frac8 * 3; // This doesn't quite work, leaving frac8 with the original numerator/denominator

I just don't see quite why frac3 = frac4 * 2 works but frac8 = frac8 * 3 does not. Any ideas? Using the const keyword in the assignment operator I found not to be the solution.

SteveC
  • 398
  • 1
  • 5
  • 11
  • Well, right now your assignment operator is defined to change nothing...you probably want to assign to some member variables. :) – GManNickG Aug 21 '12 at 22:13

3 Answers3

5

How do you expect that your operator= does anything useful if in its body you just do return *this;? You have to assign to the fields of this the fields of rightSide.

But, more importantly, if your class doesn't manage resources that need some particular treatment in case of copy you can just get away with the compiler-provided assignment operator. It simply copies the fields of one instance into the other, which, for a fraction class, seems perfectly fine.

By the way, usually you implement "regular" operators using their compound counterparts; you may want to have a look at the operator overloading FAQ.

Community
  • 1
  • 1
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • Thanks for the link. I hadn't quite realized the default copy would work in this case. This was mostly for learning/practice anyway. – SteveC Aug 21 '12 at 22:58
1

None of your assignments work, since you assignment operator implementation is empty and does nothing besides returning a reference to its left-hand side.

I.e. none of these three assignments

frac1 = frac2;
frac3 = frac4 * 2;
frac5 = frac6 * frac7;

really work.

For some reason you claim that the above assignments "work", but that must be some sort of confusion on your part. They don't "work". Neither does frac8 = frac8 * 3, for the very same reason.

P.S. I suspect that your "working" statements were in reality written this way

fraction frac1 = frac2;
fraction frac3 = frac4 * 2;
fraction frac5 = frac6 * frac7;

This might indeed work. But this syntax has nothing to do with assignment operator. Assignment operator is not used in such cases. This syntax corresponds to copy-initialization. It relies on the copy-constructor of the class (at least conceptually), not on the assignment operator. This is why it might work, while the true assignment doesn't work because you "incapacitated" the copy-assignment operator by making it empty.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • I believed they worked after verifying by calling a functions toString() method and outputting it to the console. For example; I initialized a fraction, say frac1, and then set frac2 equal to frac1. frac2 assumes frac1's attributes and remains what it should be even if frac1 is changed by any means. So to say that it doesn't ""work"" is puzzling. It was working as intended in the given examples. – SteveC Aug 21 '12 at 22:55
  • @user1450120: That would mean that the values you *expected* to see in the left-hand side objects somehow got there by accident, without any help from your assignment operator. This [mis]led you to believe that your assignment operator was somehow working, while in reality it wasn't. – AnT stands with Russia Aug 21 '12 at 23:19
  • Interesting, I didn't think `fraction frac3 = frac4 * 2;` would differ from `frac3 = frac4 * 2;` Thanks for the info. I did confirm that initializing frac3 before using the assignment operator left me with the undesired effects. Thanks. – SteveC Aug 21 '12 at 23:56
0

Your assignment operator is only returning the object itself (i.e., *this) ... so in your last example, it's simply a no-op rather than performing an actual assignment operation from the right-hand-side object. In other words a temporary fraction object is created by your operator*, but because your assignment operator does not copy the right-hand-side object's values, you end up simply throwing away the temporary fraction instance generated by the operator* after the operator= method completes.

BTW, you may want to look into the rule-of-three when it comes to creating a user-generated assignment operator. It basically states that if you class has resources that require a user-generated assignment operator, then you should also implement a user-defined copy-constructor as well as a destructor ... the compiler-generated defaults for the latter two items will not suffice if there are resources that need to be managed beyond what would be implemented in the compiler's default implementation of those methods.

Jason
  • 31,834
  • 7
  • 59
  • 78
  • I must be confused as to what '*this' does. I thought it was the right-hand-side object. Why is it that 'frac3 = frac4 * 2;' works. It would seem that that statement should really evaluate to 'frac3 = frac4' given what you've said. Thanks for the rule-of-three link. Although this class does not have anything dynamically allocated, I'm still just trying thing to learn/practice. – SteveC Aug 21 '12 at 23:03
  • How do you know it "works"? What was the initial value of `frac4`, and what were the results of `frac3` after the expression is complete? In your example code it seems that only `frac8` is tested in a before/after manner to notice the object isn't changing. – Jason Aug 21 '12 at 23:19
  • `fraction frac8(6, 20);` `fraction frac9 = frac8 * 2;` `std::cout << "\nfrac8 = " << frac8.toStringS() << std::endl;` `std::cout << "frac9 = frac8 * 2\n" << "frac9 = " << frac9.toStringS() << std::endl;` Is some of my compiled and tested code. Output to the console is: `frac8 = 6 / 20 frac9 = frac8 * 2 frac9 = 12 / 20` The code given was severely stripped down version, meant to only express the problems I was facing. – SteveC Aug 21 '12 at 23:51
  • The expression `fraction frac9 = frac8 * 2` does *not* use the assignment operator but rather a copy-constructor, which in this case is the default copy-constructor generated by the compiler. The reason that it's using a copy-constructor is because that expression is the first declaration of `frac9`. If you had done `fraction frac9;` and then `frac9 = frac8 * 2;` you would have invoked the assignment operator you defined, and would have ended up with whatever values `frac9` was initialized with rather than copying in the value of `frac8 * 2`. – Jason Aug 22 '12 at 00:43