Mithrax
Mithrax

Reputation: 7809

Why isn't my operator overloading working properly?

I have the following Polynomial class I'm working on:

#include <iostream>

using namespace std;

class Polynomial
{
//define private member functions
private:
   int coef[100];  // array of coefficients
   // coef[0] would hold all coefficients of x^0
   // coef[1] would hold all x^1
   // coef[n] = x^n ...

   int deg;        // degree of polynomial (0 for the zero polynomial)

//define public member functions
public:
   Polynomial::Polynomial() //default constructor
   {
      for ( int i = 0; i < 100; i++ )
      {
         coef[i] = 0;
      }
   }
   void set ( int a , int b ) //setter function
   {
      //coef = new Polynomial[b+1];
      coef[b] = a;
      deg = degree();
   }

   int degree()
   {
      int d = 0;
      for ( int i = 0; i < 100; i++ )
         if ( coef[i] != 0 ) d = i;
      return d;
   }

   void print()
   {
      for ( int i = 99; i >= 0; i-- ) {
         if ( coef[i] != 0 ) {
            cout << coef[i] << "x^" << i << " ";
         }
      }
   }

   // use Horner's method to compute and return the polynomial evaluated at x
   int evaluate ( int x )
   {
      int p = 0;
      for ( int i = deg; i >= 0; i-- )
         p = coef[i] + ( x * p );
      return p;
   }

   // differentiate this polynomial and return it
   Polynomial differentiate()
   {
      if ( deg == 0 )  {
         Polynomial t;
         t.set ( 0, 0 );
         return t;
      }
      Polynomial deriv;// = new Polynomial ( 0, deg - 1 );
      deriv.deg = deg - 1;
      for ( int i = 0; i < deg; i++ )
         deriv.coef[i] = ( i + 1 ) * coef[i + 1];
      return deriv;
   }

   Polynomial Polynomial::operator + ( Polynomial b )
   {
      Polynomial a = *this; //a is the poly on the L.H.S
      Polynomial c;

      for ( int i = 0; i <= a.deg; i++ ) c.coef[i] += a.coef[i];
      for ( int i = 0; i <= b.deg; i++ ) c.coef[i] += b.coef[i];
      c.deg = c.degree();

      return c;
   }

   Polynomial Polynomial::operator += ( Polynomial b )
   {
      Polynomial a = *this; //a is the poly on the L.H.S
      Polynomial c;

      for ( int i = 0; i <= a.deg; i++ ) c.coef[i] += a.coef[i];
      for ( int i = 0; i <= b.deg; i++ ) c.coef[i] += b.coef[i];
      c.deg = c.degree();

      for ( int i = 0; i < 100; i++) a.coef[i] = c.coef[i];
      a.deg = a.degree();

      return a;
   }

   Polynomial Polynomial::operator -= ( Polynomial b )
   {
      Polynomial a = *this; //a is the poly on the L.H.S

      Polynomial c;

      for ( int i = 0; i <= a.deg; i++ ) c.coef[i] += a.coef[i];
      for ( int i = 0; i <= b.deg; i++ ) c.coef[i] -= b.coef[i];
      c.deg = c.degree();


      for ( int i = 0; i < 100; i++) a.coef[i] = c.coef[i];
      a.deg = a.degree();

      return a;
   }

   Polynomial Polynomial::operator *= ( Polynomial b )
   {
      Polynomial a = *this; //a is the poly on the L.H.S
      Polynomial c;

      for ( int i = 0; i <= a.deg; i++ )
         for ( int j = 0; j <= b.deg; j++ )
            c.coef[i+j] += ( a.coef[i] * b.coef[j] );
      c.deg = c.degree();

      for ( int i = 0; i < 100; i++) a.coef[i] = c.coef[i];
      a.deg = a.degree();

      return a;
   }

   Polynomial Polynomial::operator - ( Polynomial b )
   {
      Polynomial a = *this; //a is the poly on the L.H.S
      Polynomial c;

      for ( int i = 0; i <= a.deg; i++ ) c.coef[i] += a.coef[i];
      for ( int i = 0; i <= b.deg; i++ ) c.coef[i] -= b.coef[i];
      c.deg = c.degree();


      return c;
   }

   Polynomial Polynomial::operator * ( Polynomial b )
   {
      Polynomial a = *this; //a is the poly on the L.H.S
      Polynomial c;

      for ( int i = 0; i <= a.deg; i++ )
         for ( int j = 0; j <= b.deg; j++ )
            c.coef[i+j] += ( a.coef[i] * b.coef[j] );
      c.deg = c.degree();
      return c;
   }
};

int main()
{
   Polynomial a, b, c, d;
   a.set ( 7, 4 ); //7x^4
   a.set ( 1, 2 ); //x^2

   b.set ( 6, 3 ); //6x^3
   b.set ( -3, 2 ); //-3x^2

   c = a - b; // (7x^4 + x^2) - (6x^3 - 3x^2)
   a -= b;

   c.print();
   cout << "\n";


   a.print();
   cout << "\n";


   c = a * b; // (7x^4 + x^2) * (6x^3 - 3x^2)
   c.print();

   cout << "\n";

   d = c.differentiate().differentiate();
   d.print();

   cout << "\n";

   cout << c.evaluate ( 2 ); //substitue x with 2

   cin.get();
}

Now, I have the "-" operator overloaded and it works fine:

Polynomial Polynomial::operator - ( Polynomial b )
   {
      Polynomial a = *this; //a is the poly on the L.H.S
      Polynomial c;

      for ( int i = 0; i <= a.deg; i++ ) c.coef[i] += a.coef[i];
      for ( int i = 0; i <= b.deg; i++ ) c.coef[i] -= b.coef[i];
      c.deg = c.degree();

      return c;
   }

However, I'm having difficulty with my "-=" operator:

Polynomial Polynomial::operator -= ( Polynomial b )
   {
      Polynomial a = *this; //a is the poly on the L.H.S

      Polynomial c;

      for ( int i = 0; i <= a.deg; i++ ) c.coef[i] += a.coef[i];
      for ( int i = 0; i <= b.deg; i++ ) c.coef[i] -= b.coef[i];
      c.deg = c.degree();

      // overwrite value of 'a' with the newly computed 'c' before returning 'a'
      for ( int i = 0; i < 100; i++) a.coef[i] = c.coef[i];
      a.deg = a.degree();

      return a;
   }

I just slightly modified my "-" operator method to overwrite the value in 'a' and return 'a', and just use the 'c' polynomial as a temp.

I've put in some debug print statement and I confirm that at the time of computation, both:

c = a - b;

and

a -= b;

are computed to the same value.

However, when I go to print them, their results are different:

Polynomial a, b; a.set ( 7, 4 ); //7x^4 a.set ( 1, 2 ); //x^2

b.set ( 6, 3 ); //6x^3 b.set ( -3, 2 ); //-3x^2

c = a - b; // (7x^4 + x^2) - (6x^3 - 3x^2) a -= b;

c.print(); cout << "\n";

a.print(); cout << "\n";

Result:

7x^4 -6x^3 4x^2

7x^4 1x^2

Why is my c = a - b and a -= b giving me different results when I go to print them?

Upvotes: 3

Views: 504

Answers (3)

UncleBens
UncleBens

Reputation: 41331

Operator -= should be modifying the left-hand value (and return a reference to *this to allow chaining).

It is also common to implement these functions in terms of the other:

//random example
X& operator+= (const X& other) 
{ 
    this->sth += other.sth; 
    return *this; 
}

//free function in terms of the previous
//more verbose than needed for exposition
X operator+ (const X& lhv, const X& rhv)
{
    X result(lhv);
    result += rhv;
    return result;
}

In fact most operators can (and should) be implemented in terms of others, and there's even Boost.Operators to synthesize related operators from existing ones.

Upvotes: 1

Michael Aaron Safyan
Michael Aaron Safyan

Reputation: 95499

So, firstly, you probably want to pass around const Polynomial& instead of Polynomial to your functions, since the latter creates a copy, while the former passes by constant reference.

Secondly, I find it very strange that you are writing:

Polynomial b = *this;

Instead of writing b.coeff[i], you can simply write coef[i], since it resolves to this->coef[i]. If you absolutely must use some other variable b, though, then I suggest you use the following when reading:

const Polynomial& b = *this;

And use the following when writing:

Polynomial& b = *this;

Note that if you use Polynomial instead of Polynomial&, then your b variable is a copy and is not identical to *this; consequently, changes you make will not affect *this as intended.

That said, writing deg = //... is clearer than a.deg = //..., where a represents *this. I strongly suggest you get out of the habit of creating variables that (attempt to) reference *this.

One last note, as has been stated in a comment, assignment operators should return a reference to the type. So, your operator=, operator+=, operator-=, etc. should return Polynomial&. The reason for this is to allow efficient chaining in an assignment statement. For example: a = b = c. If you were to return void, then this wouldn't work at all. With returning a copy of a Polynomial, it will work, but it will neeedlessly construct copies. Using a reference in this case (i.e. Polynomial&) prevents the copying.

Upvotes: 1

MSN
MSN

Reputation: 54604

Polynomial::operator -= isn't modifying this, it's modifying a copy of this. If you change Polynomial a= *this to Polynomial &a= *this, i.e., make a reference instead of a copy, it will work as you are now modifying *this through a. Also, the return value of operator <op>= is usually a reference, not a value.

Upvotes: 8

Related Questions