-3

When trying to attempt to overload operator<< in my shape.cpp, it can't seem to recognize the variables within the class, even though it is a friend of the class.

My .cpp file:

#include "Shape.h"

ostream& operator << (ostream& cout, const Shape& shapes)
{
    for (int i = 0; i < points.size(); i++) //points is undefined
    {
        cout << points[i] << endl; 
    }
}

My .h file:

#include <vector>
#include "Point.h"
#pragma once

using namespace std;

class Shape
{
    friend ostream& operator << (ostream& cout, const Shape& shapes);

    private:
        vector <Point> points; //Ordered list of vertices
};

I already used the same overload for my point class and it worked fine.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Devs
  • 1
  • 1
    `cout` is a bad name for a parameter, especially with `using namespace std;`. You need `shapes.points` since the function is not a member of the class. – Retired Ninja Jan 08 '23 at 00:05
  • 3
    Did you mean `shapes.points`? – jxh Jan 08 '23 at 00:06
  • See https://stackoverflow.com/questions/476272/how-to-properly-overload-the-operator-for-an-ostream/35811860#35811860 eg https://godbolt.org/z/fabefxTGv – QuentinUK Jan 08 '23 at 00:32
  • If you use the same overload for the point class and it worked fine, that means you did something different. Your code, as posted, has multiple problems - and the undeclared identifier is the most benign concern (since it triggered a diagnostic). The worse problem, if you fixed that, will be undefined behaviour that will probably not be diagnosed at all, but can unpredictably cause a runtime error. And there is plenty of information online about why `using namespace std` is BAD PRACTICE in a header file. – Peter Jan 08 '23 at 00:54

1 Answers1

1

A friend function is not a class member. It can be treated as any other non-class function. Except that, because it's a friend, it has access to its private members:

ostream& operator << (ostream& cout, const Shape& shapes)
{
    for (int i = 0; i < shapes.points.size(); i++)
    {
        cout << shapes.points[i] << endl; 
    }
}

It should now be clear that the object gets passed in as the shapes parameter. Well, it's points member must, therefore, be shapes.points.

However, we can do even better than that. How about using range iteration?

ostream& operator << (ostream& cout, const Shape& shapes)
{
    for (auto &v:shapes.points)
    {
        cout << v << endl; 
    }
}
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148