0

I've got a class with the following declaration and accompanying definition:

friend ostream& operator<<(ostream& out, const Poly& poly);
ostream& operator<<(ostream& out, const Poly& poly) {}

and

private:
    int *polyArray;

Inside the code for that operator function, I have (among other things):

    if (poly.polyArray[i] != 0) {
        out << poly.polyArray[i];
    }

I get the following error message from an underline in my compiler (Visual Studio) specifically underneath "polyArray":

int *Poly::polyArray 
Member "Poly::polyArray" is inaccessible

I'm able to call public member functions just fine, and I thought I was able to access a private data member from a friend function.

Any ideas on why I'm getting this error?

NOTE: Below is more of the complete class, as requested:

First, the header file.

class Poly
{
public:
    Poly(int coeff, int expon);
    friend ostream& operator<<(ostream& out, const Poly& poly);
private:
    int *polyArray;
    int size;
};

Then the implementation.

#include <iostream>
#include "Poly.h"

using namespace std;

Poly::Poly(int coeff, int expon) {
    size = expon + 1;
    polyArray = new int[size];
    for (int i = 0; i < size; ++i) {
        polyArray[i] = (i == expon ? coeff : 0);
    }
}

ostream& operator<<(ostream& out, const Poly& poly) {
    int currentSize = poly.getSize();
    // If Poly is "empty", print 0
    if (currentSize == 1 && poly.polyArray[0] == 0) {
        out << 0;
        return out;
    }
    for (int i = 0; i < currentSize; ++i) {
        // Print the "+" sign if the coefficient is positive
        //if (poly.polyArray[i] > 0) {
        if (poly.polyArray[i] > 0) {
            out << "+";
        }
        // Print the coefficient if it is not 0, skipping it and all following code otherwise
        if (poly.polyArray[i] != 0) {
            out << poly.polyArray[i];
        }
        else {
            continue;
        }
        // Print "x" if the exponent is greater than 0
        if (i > 0) {
            out << "x";
        }
        // Print exponent if it is greater than 1
        if (i > 1) {
            out << "^" << i;
        }
        // Print a space if this is not the last term in the polynomial
        if (i != currentSize - 1) {
            out << " ";
        }
    }
    return out;
}

Finally, main.

#include "Poly.h"
#include <iostream>

using namespace std;

int main() {
    Poly y(5, 7);
    cout << y;
    return 0;
}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Tyler M.
  • 115
  • 1
  • 1
  • 11

1 Answers1

1

A directive to use a namespace (e.g. using namespace std) only applies to code and header files written after the directive.

In your header file, Poly.h, there's no definition for ostream because ostream is in namespace std. There are three possible fixes:

  • using namespace std in the header file (bad practice)
  • using std::ostream in the header file
  • Use the full name of std::ostream

    friend std::ostream& operator<<(std::ostream& out, const Poly& poly);

If we apply the second fix, this is what our files look like now.

Poly.h

#include <iostream>

using std::ostream; 

class Poly
{
public:
    Poly(int coeff, int expon);
    friend ostream& operator<<(ostream& out, const Poly& poly);
private:
    int *polyArray;
    int size;
};

Poly.cc

#include <iostream>
#include "Poly.h"
using namespace std;

Poly::Poly(int coeff, int expon) {
    size = expon + 1;
    polyArray = new int[size];
    for (int i = 0; i < size; ++i) {
        polyArray[i] = (i == expon ? coeff : 0);
    }
}

ostream& operator<<(ostream& out, const Poly& poly) {
    int currentSize = poly.getSize();
    // If Poly is "empty", print 0
    if (currentSize == 1 && poly.polyArray[0] == 0) {
        out << 0;
        return out;
    }
    for (int i = 0; i < currentSize; ++i) {
        // Print the "+" sign if the coefficient is positive
        //if (poly.polyArray[i] > 0) {
        if (poly.polyArray[i] > 0) {
            out << "+";
        }
        // Print the coefficient if it is not 0, skipping it and all following code otherwise
        if (poly.polyArray[i] != 0) {
            out << poly.polyArray[i];
        }
        else {
            continue;
        }
        // Print "x" if the exponent is greater than 0
        if (i > 0) {
            out << "x";
        }
        // Print exponent if it is greater than 1
        if (i > 1) {
            out << "^" << i;
        }
        // Print a space if this is not the last term in the polynomial
        if (i != currentSize - 1) {
            out << " ";
        }
    }
    return out;
}

main.cc

#include <iostream>
#include "Poly.h"

using namespace std; 

int main() {
    Poly y(5, 7);
    cout << y;
    return 0;
}
Fureeish
  • 12,533
  • 4
  • 32
  • 62
Alecto Irene Perez
  • 10,321
  • 23
  • 46
  • You and the other poster have the same idea about the mismatch, so I edited my original post with a copy/paste of the definition header. Take a look - what am I missing? – Tyler M. Jan 11 '19 at 06:05
  • Could you post a minimal code example that doesn't compile? Like could you post a complete class, the main method, and the friend method? – Alecto Irene Perez Jan 11 '19 at 07:37
  • Sure, I just now edited my original post with the relevant info. – Tyler M. Jan 11 '19 at 17:30
  • Header doesn't actually need `` - `` is sufficient (and minimal). – davidbak Jan 11 '19 at 20:49
  • Wow, ok. Three questions for you. One, why is it bad practice to have "using namespace std;" in the header file? Two, why does ostream being in the std namespace prevent a friend function from accessing a private data member? And three, what's the purpose of including iostream in the header? – Tyler M. Jan 11 '19 at 21:33
  • 1
    First question: "using namespace std" is considered bad practice because it increases the likelihood of two different classes having the same name. For example, if there's `std::string`, but also `boost::string`, and you use both namespaces, there'll be a collision (since they're both name string). Second question: *it doesn't*. You can still use a friend function to access private data members. Third question: the purpose of including iostream in the header is that you always have to include a header before you use classes defined in that header file. – Alecto Irene Perez Jan 11 '19 at 21:42
  • In your main file, for example, you include `Poly.h` before you include `iostream` (so the code fails to compile). But if you included `iostream` in Poly (or `iosfwd`, as someone else suggested), then you don't have to worry about the order of includes. – Alecto Irene Perez Jan 11 '19 at 21:44
  • Ok, so since ostream is in namespace std and, presumably, some other namespace, I have to somehow specify WHICH ostream I'm using. In this case, I'm using std::ostream, and when I specify that, it all lines up. And then this... somehow... allows that specific function to access private data members. Right? – Tyler M. Jan 11 '19 at 22:04
  • Basically yes - have to specify which ostream you're using. Writing "using namespace std" is one way of specifying it, but it means you're specifying that you're using literally everything in namespace std (which increases the chance of two names conflicting). That's why it's recommended to either use the full name "std::ostream", or to specify you're using std::ostream specifically (with "using std::ostream;") – Alecto Irene Perez Jan 12 '19 at 01:02
  • Got it, thanks a ton for all the help! Complicated issue from my point of view! – Tyler M. Jan 13 '19 at 02:55