为什么我的运算符重载不能正常工作?

时间:2010-04-14 19:06:02

标签: c++

我正在进行以下多项式课程:

#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();
}

现在,我已经重载了“ - ”运算符,它运行正常:

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();

      // 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;
   }

我只是稍微修改了我的“ - ”运算符方法来覆盖'a'中的值并返回'a',并且只使用'c'多项式作为临时值。

我已经输入了一些调试打印语句,我确认在计算时,两者都是:

  

c = a - b;

  

a - = b;

计算为相同的值。

然而,当我去打印它们时,它们的结果是不同的:

  

多项式a,b; a.set(7,4);   // 7x ^ 4 a.set(1,2); // X ^ 2

     

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

     

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

     

c.print(); cout&lt;&lt; “\ n” 个;

     

a.print(); cout&lt;&lt; “\ n” 个;

结果:

  

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

     

7x ^ 4 1x ^ 2

为什么我的c = a - ba -= b在打印时会给我不同的结果?

3 个答案:

答案 0 :(得分:8)

Polynomial::operator -=未修改this,它正在修改this的副本。如果您将Polynomial a= *this更改为Polynomial &a= *this,即创建引用而不是副本,则可以使用*thisa进行修改。此外,operator <op>=的返回值通常是引用,而不是值。

答案 1 :(得分:1)

所以,首先,您可能希望将const Polynomial&而不是Polynomial传递给您的函数,因为后者会创建一个副本,而前者会通过常量引用传递。

其次,我觉得你写作很奇怪:

Polynomial b = *this;

您可以简单地编写b.coeff[i],而不是撰写coef[i],因为它会解析为this->coef[i]。但是,如果您绝对必须使用其他变量b,那么我建议您在阅读时使用以下内容:

const Polynomial& b = *this;

写作时使用以下内容:

Polynomial& b = *this;

请注意,如果您使用Polynomial代替Polynomial&,那么您的b变量是副本,与*this不同;因此,您所做的更改不会按预期影响*this

尽管如此,写deg = //...a.deg = //...更清晰,其中a代表*this。我强烈建议您不要创建(尝试)引用*this的变量。

最后一点,正如评论中所述,赋值运算符应该返回对类型的引用。因此,您的operator=operator+=operator-=等应返回Polynomial&。这样做的原因是允许在赋值语句中进行有效链接。例如:a = b = c。如果您要返回void,那么这根本不起作用。返回Polynomial的副本,它将起作用,但它将无需构建副本。在这种情况下使用引用(即Polynomial&)可防止复制。

答案 2 :(得分:1)

运算符-=应该修改左侧值(并返回对*this的引用以允许链接)。

以另一种方式实现这些功能也很常见:

//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;
}

事实上,大多数运营商可以(而且应该)以其他运营商的方式实施,甚至Boost.Operators来合成现有运营商的相关运营商。