Search code examples
c++scopeoperator-overloadingfriend

Scope of Variable in Friend Operator


For one of our class assignments we had to implement a polynomial class. It stores the coefficients of a polynomial and outputs the answer.

In my class definition, I have a friend operator that outputs the function:

friend std::ostream& operator << (std::ostream& out, Polynomial& p);

and my implementation is as follows:

std::ostream& operator << (std::ostream& out, Polynomial& p) {
    double ans = 0;

    for(int i = 0; i <= p.order; ++i)
        ans += (double)p.coefficents[i] * pow(p.x, i);

    out << ans;

    return out;
}

My main function (written by my instructor) is:

int main ()
{
    Polynomial p1 (0.5,3); // Invokes two argument constructor for p1
    p1.inputCoefficients(); // Set the coefficient of polynomial p1
    cout << "Polynomial p1 evaluates to " << p1 << endl; 
    Polynomial p2(p1), p3; // Copy constructor for p2 and default constructor for p3
    cout << "Polynomial p2 evaluates to " << p2 << endl; 
    cout << "Polynomial p3 evaluates to " << p3 << endl;
    p3 = p2; // Copy assignment operator
    return 0;

}

My question is: When I run my program with this line of code:

double ans = 0;

my output is this:

Polynomial p1 evaluates to 1.375
Polynomial p2 evaluates to 1.375
Polynomial p3 evaluates to 0
Polynomial destroyed!
Polynomial destroyed!
Polynomial destroyed!

Which is the correct output but if I change that line to this:

double ans;

Unexpected things start to happen:

Polynomial p1 evaluates to 1.375
Polynomial p2 evaluates to 1.375
Polynomial p3 evaluates to 1.375
Polynomial destroyed!
Polynomial destroyed!
Polynomial destroyed!

Why is p3 evaluated to 1.375? p3 was created using the default constructor so wouldn't it output 0?

As soon as the polynomial is outputted wouldn't the scope of ans die? Even if it didn't, or ans kept the value from the last time it ran, then wouldn't p2 be doubled (be 2.75) because the << operator ran twice? Please feel free to get technical and offer advice, I'm curious and want to know the insides of what's actually going on.

Here is the entirety of my code (for reference):

/*
Using dynamic arrays, implement a polynomial class. In mathematics, polynomial is a function of the form f(x) = a0*x^0 + a1*x^1 + a2*x^2 + a3*x^3 + ....n terms. Here, a0, a1, a2 etc. are the coefficients of the polynomial and n is the order of the polynomial.


The private variables include the value of x (a real number), the order of the polynomial (an integer) and the dynamic array that stores the coefficients (real numbers).

The public methods include

a. default constructor that sets the value of x to zero and the order to 0,
b. a two argument constructor that takes as arguments the value of x and the order of the polynomial. The values of the coefficients are set to zero.
c. inputCoefficients(): prompts the user to input the value of the coefficients of the polynomial. For this homework, skip the user input. Instead assign the coefficent values equal to the index of the position in the array. For example, a0 = 0, a1 = 1, a2 = 2 and so on depending on the order of the particular polynomial object
c. a copy constructor
d. << operator overloaded that returns the value of the polynomial (obtained by evaluating the polynomial). 
e. == overloaded (copy assignment operator)
f. destructor. Deallocates dynamic arrays and prints a message "Polynomial destroyed! "

Below is the testing program - 
*/

#include <iostream>
using std::cin;
using std::endl;
using std::cout;
#include <cmath>

class Polynomial {
public:
    Polynomial() {
        x = 0,
        order = 0;
        coefficents = new double[order + 1];
    }

    Polynomial(const double x, const int order) {
        this->x = x;
        this->order = order;

        this->coefficents = new double[order + 1];

        for(int i = 0; i <= order; ++i)
            this->coefficents[i] = 0;
    }

    Polynomial(const Polynomial& p) {
        this->x = p.x;
        this->order = p.order;

        this->coefficents = new double[this->order];

        for(int i = 0; i <= this->order; ++i)
            this->coefficents[i] = p.coefficents[i];
    }

    ~Polynomial() {
        std::cout << "Polynomial destroyed! " << std::endl;
        delete[] coefficents;
    }

    void inputCoefficients() {
        /*
        for(auto& num: coefficents) {
            std::cout << "Enter the next coefficent:: ";
            std::cin >> num;
        }
        std::cout << "Thank you" << std::endl;
        */
        for(int i = 0; i <= order; ++i) {
            coefficents[i] = i;
        }
    }

    Polynomial& operator = (const Polynomial& p) {
        this->x = p.x;
        this->order = p.order;

        delete[] this->coefficents;

        this->coefficents = new double[order + 1];

        for(int i = 0; i <= this->order; ++i)
            this->coefficents[i] = p.coefficents[i];

        return *this;
    }

    friend std::ostream& operator << (std::ostream& out, Polynomial& p);
    friend bool operator == (const Polynomial& p1, const Polynomial& p2);

private:
    double x;
    double* coefficents;
    int order;
};

std::ostream& operator << (std::ostream& out, Polynomial& p) {
    double ans;

    for(int i = 0; i <= p.order; ++i)
        ans += (double)p.coefficents[i] * pow(p.x, i);

    out << ans;

    return out;
}

bool operator == (const Polynomial& p1, const Polynomial& p2) {
    if((p1.x != p2.x) && (p1.order != p2.order))
        return false;

    for(int i = 0; i < p1.order; ++i) {
        if(p1.coefficents[i] != p2.coefficents[i])
            return false;
    }

    return true;
}



int main ()
{
    Polynomial p1 (0.5,3); // Invokes two argument constructor for p1
    p1.inputCoefficients(); // Set the coefficient of polynomial p1
    cout << "Polynomial p1 evaluates to " << p1 << endl; 
    Polynomial p2(p1), p3; // Copy constructor for p2 and default constructor for p3
    cout << "Polynomial p2 evaluates to " << p2 << endl; 
    cout << "Polynomial p3 evaluates to " << p3 << endl;
    p3 = p2; // Copy assignment operator
    return 0;

}

Solution

  • Your << function contains the line:

    ans += (double)p.coefficents[i] * pow(p.x, i);
    

    If you don't initialize ans to 0, then the initial value of ans will be indeterminate, and then you're adding each term to this. So you get a random result.

    In your case, ans is apparently holding on to its value from the previous call. And since p3 is an empty polynomial, the loop never adds anything to it, so you print the previous result.