954,500 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

overloading << not working

I have 2 classes, Edge and Point. Edge contains Point P1 and Point P2 as private memebers. Edge has accessor functions

Point getP1()
{
return P1;
}

and the same for P2.

Point has << overloaded -

ostream & operator << (ostream &output, Point &p);

I am trying to overload << for Edge:

ostream & operator << (ostream &output, Edge &e);

this works fine:

ostream & operator << (ostream &output, Edge &e)
{
Point x = e.getP1();
Point y = e.getP2();

output << "P1: " << x << " P2: " << y;

return output;
}

but this doesn't work:

ostream & operator << (ostream &output, Edge &e)
{
output << e.getP1() << " " << e.getP2();
return output;
}

The compiler says "Error: no match for operator << in output << Edge::getP1()()"

First, why are there two sets of parentheses in the compilers message?

Second, why does this happen?

Thanks!

Dave

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

Point is not a POD (plain old data) type so you must either create overload << operator for it too or print each part separately

struct Point
{
  int x, y;
};

...
ostream & operator << (ostream &output, Edge &e)
{

    Point p1, p2;
    p1 = e.getP1();
    p2 = e.getP2();
   output << p1.x << " " << p1.y << " " << p2.x << " " << p2.y;
   return output;
}


or

struct Point
{
  int x, y;

};
ostream & operator << (ostream &output, Point &p)
{
   output << p.x << " " << p.y;
  return output;
}

...
ostream & operator << (ostream &output, Edge &e)
{

   output << e.getP1() << " " << e.getP2();
   return output;
}
Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

In the original post I mentioned that I have already overloaded << for Point. And also since the operator<< has to be public (I could make it friend, but i chose not to), it has to look like this

ostream & operator << (ostream &output, Point &p)
{
output << p.getX() << " " << p.getY();
return output;
}

Is there anything else I can check??

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

>>In the original post I mentioned that I have already overloaded << for Point.
Yes you did and I missed it.

>>Is there anything else I can check??
don't know without seeing the entire code. Try my first suggestion to see if that compiles.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

Ok I made a simple demo program that does exactly the same thing, now I get a different error though:

In geom_Edge.h (on this line "geom_Point P1")
error: field P1 has incomplete type

geom_Point.h

#include <iostream>
using namespace std;

class geom_Point
{
	double x;
	double y;
	double z;
public:
	double getX();
	double getY();
	double getZ();
	
	//default constructor
	geom_Point()
	{
	
	}

};

ostream & operator << (ostream &output, geom_Point &p);


geom_Point.cpp

#include "geom_Point.h"

double geom_Point::getX()
{
	return x;
}

double geom_Point::getY()
{
	return y;
}

double geom_Point::getZ()
{
	return z;
}


ostream & operator << (ostream &output, geom_Point &p)
{
	output << p.getX() << " " << p.getY();
	return output;
}


geom_Edge.h

#include <iostream>
using namespace std;

class geom_Point; //forward declaration

class geom_Edge
{
	geom_Point P1;
	geom_Point P2;
public:
	geom_Point getP1();
	geom_Point getP2();
	//default constructor
	geom_Edge()
	{

	}
};

ostream & operator << (ostream &output, geom_Edge &e);


geom_Edge.cpp

#include "geom_Edge.h"

ostream & operator << (ostream &output, geom_Edge &e)
{
	output << e.getP1() << " " << e.getP2();
	return output;
}

geom_Point geom_Edge::getP1()
{
	return P1;
}

geom_Point geom_Edge::getP2()
{
	return P2;
}
daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

forward declarations only allow you to declare pointers to the class. If you want to declare an actual object then you need to include the entire header so that the compiler knows that the class looks like. Maybe this will work -- make P1 and P2 pointers in the .h file, then move the class constructor to the *.cpp file where you can allocate memory for them. You also have to change the get functions.

#include <iostream>
using namespace std;

class geom_Point; //forward declaration

class geom_Edge
{
	geom_Point* P1;
	geom_Point* P2;
public:
	geom_Point getP1();
	geom_Point getP2();
	//default constructor
};

ostream & operator << (ostream &output, geom_Edge &e);
#include "geom_Edge.h"

// class constructor
geom_Edge::geom_Edge()
{
    P1 = new geom_Point;
    P2 = new geom_Point;
}

ostream & operator << (ostream &output, geom_Edge &e)
{
	output << e.getP1() << " " << e.getP2();
	return output;
}

geom_Point geom_Edge::getP1()
{
	return *P1;
}

geom_Point geom_Edge::getP2()
{
	return *P2;
}
Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

Sorry, I don't know why I used a forward declaration. SInce geom_Edge is not used in geom_Point, I can simply #include "geom_Point.h" in geom_Edge like so:

geom_Edge.h

#include <iostream>
using namespace std;

#include "geom_Point.h"

class geom_Edge
{
	geom_Point P1;
	geom_Point P2;
public:
	geom_Point getP1();
	geom_Point getP2();
	//default constructor
	geom_Edge()
	{

	}
};

ostream & operator << (ostream &output, geom_Edge &e);


NOW I am back to the << problem (phew, i was hoping it wouldn't just go away hahaha)

Try it with that geom_Edge.h and see what you get.

error: no match for 'operator<<' in 'output << ((geom_Edge*)e)->geom_Edge::getP1()'

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

using VC++ 2008 Express I didn't get any errors or warnings on that code. I created a new project, added the four files to it, created my own main() which was an empty function, and it compiled ok.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

Ah I forgot to mention - neither do I!! I am trying to compile it with g++ (through KDevelop) because I have to make a linux static library (.a) file. I thought that g++ was much stricter about some things than VS. Can you try it on linux? I've tried it on 2 machines and got the same error both times.

-Dave

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

>>Can you try it on linux?
No -- I don't do linux :)

When I bump up the compiler's warning level I get these warnings

geom_Edge.cpp
d:\dvlp\test4\test4\geom_edge.cpp(7) : warning C4239: nonstandard extension used : 'argument' : conversion from 'geom_Point' to 'geom_Point &'
        A non-const reference may only be bound to an lvalue
d:\dvlp\test4\test4\geom_edge.cpp(7) : warning C4239: nonstandard extension used : 'argument' : conversion from 'geom_Point' to 'geom_Point &'
        A non-const reference may only be bound to an lvalue
geom_Point.cpp

Maybe that is what g++ is talking about ?

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

GOT IT!! I had to make the accessor functions const!

geom_Point getP1() const;

weird... why do you not have to do that in VS?

daviddoria
Posting Virtuoso
1,996 posts since Feb 2008
Reputation Points: 437
Solved Threads: 204
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You