2

So I have the += operator overloaded in a way that attempts to take advantage of the + operator that I've already defined. Namely that Polynomial + Polynomial returns a new Polynomial. So my += function basically tries to call this + function with the LHS as *this and the RHS as *this + B (where B is a Polynomial object passed by const reference to the function). I am getting an error. Where am I going wrong with this?

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cmath>

using namespace std;
void line(int lines);


class Polynomial
{
    private:
        int degree;
        double* coeffs;
    public:
        //constructors
        Polynomial() {degree=0;coeffs=new double[1];}
        Polynomial(int deg) {degree=deg;coeffs=new double[deg+1];}
        Polynomial(const Polynomial& A);

        //mutators
        void GetCoeffs(istream& in);
        void EditCoeff(int deg);
        void ResetCoeffs();
        int Coeff(int deg);
        void Randomize(int max);

        //accessors
        void Show(ostream& out);
        int Degree() {return degree;}

        //operators
        Polynomial operator+(const Polynomial& B); //Polynomial + Polynomial
        friend Polynomial operator +(double c, Polynomial& A); //c + Polynomial
        Polynomial operator +(double c); //Polynomial + c
        void operator +=(const Polynomial& B); //Polynomial+=Polynomial
        void operator =(Polynomial& A);
        Polynomial operator*(int k);
        Polynomial operator*(Polynomial& A);

};



int main()
{
    Polynomial A(5);
    A.Randomize(4);
    A.Show(cout);
    line(2);
    Polynomial B=A+8;
    B.Show(cout);




    return 0;
}

Polynomial Polynomial::operator*(int k)
{
    Polynomial C(degree);
    C=*this;
    for (int i=degree; i>=0; i--)
        C.coeffs[i]*=k;
    return C;
}

Polynomial operator +(double c, Polynomial& A)
{
    Polynomial C=A;
    C.coeffs[0]+=c;
    return C;
}
Polynomial Polynomial::operator +(double c)
{
    Polynomial C=*this;
    C.coeffs[0]+=c;
    return C;
}

void Polynomial::Randomize(int max)
{
    for (int i=degree; i>=0; i--)
    {
        coeffs[i]=rand()%(max+1) + 1;
        if ((rand()%(101) + 1)%2 == 0)
            coeffs[i]*=-1;
    }
}

void Polynomial::operator =(Polynomial& A)
{
    if (degree==A.degree)
    {
        for (int i=degree; i>=0; i--)
        {
            coeffs[i]=A.coeffs[i];
        }
    }
}

Polynomial Polynomial::operator+(const Polynomial& B)
{

    if (degree>=B.degree)
    {
        Polynomial C(degree);
        C=*this;

        for (int i=B.degree; i>=0; i--)
        {
            C.coeffs[i]=coeffs[i]+B.coeffs[i];
        }
        return C;
    }
    else
    {
        Polynomial C=B;

        for (int i=degree; i>=0; i--)
        {
            C.coeffs[i]=coeffs[i]+B.coeffs[i];
        }
        return C;

    }

}

void Polynomial::operator+=(const Polynomial& B)
{
    *this = (*this + B);
}

int Polynomial::Coeff(int deg)
{
    return coeffs[deg];
}

void line(int lines)
{
    for (int i=0; i<lines; i++)
        cout << endl;
}

void Polynomial::GetCoeffs(istream& in)
{
    for (int i=degree; i>=0; i--)
    {
        in >> coeffs[i];
    }
    in.ignore();
}

void Polynomial::Show(ostream& out)
{

    if (coeffs[degree]>0)
                cout << "   ";
    for (int i=degree; i>=0; i--)
    {


        if (coeffs[i]>=0)
        {
            if (i!=degree)
                out << " + ";
            out << coeffs[i];


        }
        else
        {
            if (coeffs[i]<0)
                out << " - ";
                out << 0-coeffs[i];
        }
        if (i>1)
            out << "x^" << i;
        else if (i==1)
            out << "x";

    }
}

Polynomial::Polynomial(const Polynomial& A)
{
    coeffs=new double[A.degree+1];
    degree=A.degree;
    for (int i=A.degree; i>=0; i--)
    {
        coeffs[i]=A.coeffs[i];

    }

}

Polynomial Polynomial::operator*(Polynomial& A)
{
    int deg=A.degree+degree;
    Polynomial P(deg);

    for (int i=deg; i>=0; i--)
        P.coeffs[i]=0;



    for (int i=deg; i>=0; i--)
    {
        for (int j=A.degree; j>=0; j--)
        {
            P.coeffs[i+j]+=coeffs[i]*A.coeffs[j];
        }
    }

    return P;


}
BrownBeard93423
  • 179
  • 5
  • 15
  • 2
    I highly recommend you use `std::vector` instead of `double *`. – chris Oct 16 '12 at 02:29
  • in the operator =+ definition it says it doesn't recognize the function (the line that reads " *this=(*this+B) " ) – BrownBeard93423 Oct 16 '12 at 02:46
  • Please see [Operator overloading](http://stackoverflow.com/questions/4421706/operator-overloading) for some good guidelines. – Blastfurnace Oct 16 '12 at 02:52
  • there is no explicit destructor which is going to deallocate the double coeffs; memory, that's why @chris suggested to use a std::vector which is a little bit easier to manage. – Nusrat Nuriyev Jul 17 '23 at 12:07

3 Answers3

3

Your problem is that *this + B is a temporary, and temporary objects can't be bound to non-const references.

Of course, there's no reason that the RHS of an assignment can't be const. Try:

void operator=(/* HERE */ const Polynomial& A);

Most of your other operators aren't using const where they should either. For example:

Polynomial operator+(const Polynomial& B) /* HERE */ const; //Polynomial + Polynomial
friend Polynomial operator +(double c, /* HERE */ const Polynomial& A); //c + Polynomial

Only assignment operators should be non-const members, and they should accept const right operands. Normal binary operators that create new objects should be const wrt both left and right operands.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • What do you mean by "temporary objects can't be bound to non-const references" ? – BrownBeard93423 Oct 16 '12 at 03:18
  • I mean exactly that. If you have `int i; void f(int&);` you can't say `f(i+4);`, because `i+4` is a temporary, not an lvalue, and `f(int&)` accepts only an lvalue reference. – Ben Voigt Oct 16 '12 at 05:42
  • Remember that you overrode `operator=`, so the line `*this = *this + B;` turns into `this->operator=(this->operator+(B))`. Your `operator+` returns a temporary value, `operator=` needs an lvalue. By changing the signature to include `const` like I showed, the temporary becomes acceptable. – Ben Voigt Oct 16 '12 at 05:44
  • What if we have somthing like *this = *this + B + T ? T (is some temporary object), how then this call is looked ? this->operator=((this->operator+(B)).operator+(T)), and why? well when we are talking about integers, c = a + b + c; it is obvious, first right part is evaluated and assigment is done, because assignment operator has lower priority. but how this works for operator= and operator+ ? – Nusrat Nuriyev Jul 17 '23 at 13:14
  • 1
    @NusratNuriyev: Operator precedence depends only on the tokens (`=` and `+`) and not on the types involved. When a type overloads operators, it changes the behavior but cannot change the precedence. – Ben Voigt Jul 17 '23 at 14:30
1

Often it is done other way around. People make binary + operator (usually non-member) that takes advantage of += operator (a member) that is already defined.

Öö Tiib
  • 10,809
  • 25
  • 44
  • 2
    Specifically, `Polynomial operator+(Polynomial lhs, const Polynomial& rhs) { return lhs += rhs; }` – Robᵩ Oct 16 '12 at 02:35
  • 1
    I acknowledge that's the case and I appreciate you pointing that out, but I still need to understand why my specific code isn't working. It's not enough for me to understand a different way of doing it that does work, I need to know why this fails :/ – BrownBeard93423 Oct 16 '12 at 02:51
1

Where am I going wrong with this?

  • You should use std::vector instead of a raw pointer.
  • You have violated the rule of three.
  • You didn't follow the convention creating a member operator+= and a free operator+.

Try this:

// UNTESTED
class Polynomial
{
    private:
        std::vector<double> coeffs;

    public:
        //constructors
        Polynomial() : coeffs(1) {}
        Polynomial(int deg) : coeffs(deg+1) {}
        // Don't need copy constructor
        // Don't need destructor
        // Don't need assignment operator

        ...
        int Degree() {return coeffs.size()-1;}

        //operators
        Polynomial& operator+=(const Polynomial& B) {
            if(Degree() < B.Degree())
              coeffs.resize(B.Degree()+1);
            for(int i = 0; i <= B.Degree(); ++i)
              coeffs[i] += B.coeffs[i];
            return *this;
        }    
};

Polynomial operator+(Polynomial A, const Polynomial& B) {
  return A += B;
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • am i correct in thinking you return the class object in your += function so you can chain += statements (i.e. A += B += C) ? – BrownBeard93423 Oct 16 '12 at 05:15
  • like i mentioned to the other guy, I very much appreciate being shown the orthodox ways that DO work, but even more valuable to me than that is if I can understand why my code did not work, especially the line *this = *this + B ... I don't completely understand Ben Voigt's explanation of why that line failed. – BrownBeard93423 Oct 16 '12 at 05:18