overloading << not working

I have 2 classes, Edge and Point. Edge contains Point P1 and Point P2 as private memebers. Edge has accessor functions
1
2
3
4
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:
1
2
3
4
5
6
7
8
9
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:
1
2
3
4
5
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
Last edited on
In the second case you are 'telling' to the compiler to use the overloaded << operator which has not been implemented.
In other words you can use the overloaded << operator outside its implementation only.
Last edited on
Change the last parameter of both operator functions to const reference.
1
2
const Point& p
const Edge& e
here are some simple files that will actually compile:

as you can see I put the const in the operator functions. it now complains:
error: passing 'const geom_Edge' as 'this' argument of 'geom_Point geom_Edge::getP1()' discards qualifiers

geogeplusplus: The second case is trying to use the operator<< defined for Point inside the operator<< defined for Edge, this should be ok?

Any other thoughts?

test.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include <iostream>
#include "geom_Point.h"
#include "geom_Edge.h"

using namespace std;

int main(int argc, char *argv[])
{
  cout << "test" << endl;

  return EXIT_SUCCESS;
}


geom_Point.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#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, const geom_Point &p);


geom_Edge.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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, const geom_Edge &e);


geom_Point.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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, const geom_Point &p)
{
	output << p.getX() << " " << p.getY();
	return output;
}


geom_Edge.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "geom_Edge.h"

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

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

geom_Point geom_Edge::getP2()
{
	return P2;
}
Last edited on
turns out you have to make the accessors const members functions

geom_Point getP1() const;

not sure why?
The member functions getP1() and getP2() have to be declared const because you are attempting to access them through a const instance of geom_Edge. (const geom_Edge &e in your overloaded streaming operators)

Whenever you create a const instance of an object, it only has access to it's const member functions. Even if a non-const member function doesn't actually change the object, it is inaccessible from a const object.
@daviddoria:

If I may make a suggestion for you: Why are you prefixing all classes with "geom_"? It seems like you are implementing your own "home made namespace" scheme. Why don't you use an actual namespace instead?

Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// geom_Point.h
#include <iostream>
// using namespace std; -- You don't need this

namespace geom
{
class Point
{
	double x;
	double y;
	double z;
public:
	double getX();
	double getY();
	double getZ();
	
	//default constructor
	Point()
	: x(0.0), y(0.0), z(0.0) // Tip: Make sure these are initialized
	{
	}

};
} // End of namespace geom

// Use std namespace explicitly in header files
std::ostream & operator << (std::ostream &output, const geom::Point &p);
Here is a quick work around.

Just declare a couple of temporary objects to hold the P1 and P2 objects and use the same to output in the overloaded << function of Edge class.

The revised code would look like:

ostream & operator << (ostream &stream, geom_Edge &e)
{
geom_Point p1, p2;
p1 = e.getP1();
p2 = e.getP2();
stream << p1 << " " << p2 ;
return stream;
}

Other than this little change, you dont have to change anything in your original code.

And you better stay way from "const" part in the declaration.

Because, your getP1() and getP2() functions return temporary objects on fly whenever they are called and your overloaded function with "const" qualification would prevent it complaining that "the function may not be called for a const or volatile qualified object".
A removal of const in the overloaded parameter declaration would not have any problem calling a temporary object from a temporary (non-const) parameter.

Try it out and post the outcome.

Hope this helps.

Good luck :)


And I forgot to mention in the last note.

Normally we dont see a "function call" from overloaded << or >> operator functionality.

And noting that function calling from an overloaded << function is NOT recommended ( I guess, not allowed), you would have to access the data members of the called class directly.

First question of yours would be, how about private methods/data,
then, make the overloaded << function is a friend of your class, so that it would be able to access all of its methods and data including private and protected.

In your case, the code would look like:

// geom_Point.h
class geom_Point
{
double x;
double y;
double z;
public:
double getX();
double getY();
double getZ();

//default constructor
geom_Point()
{

}

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

};

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


// geom_Edge.h

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

}
friend ostream & operator << (ostream &output, const geom_Edge &e);

};

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


// geom_Point.cpp

ostream & operator << (ostream &output, const geom_Point &p)
{
output << p.x << " " << p.y; // access them directly, as a friend
return output;
}

// geom_Edge.cpp

ostream & operator << (ostream &output, const geom_Edge &e)
{
output << e.P1 << " " << e.P2; // get them directly too, as a friend
return output;
}



Thats all. All should go good now.

Remember, here we made the overloaded operators are "friends" of the overriding classes hence the overloaded operator functionality can access all members of the classes including private data.
So you better declare the class parameters are of "const" qualified so that, even acceidently and unintentionally, the data would not be at loss/damage.
A non-const class parameter in an overloaded << or >> function and it is a friend of the called class, is a design issue. Not at all recommended.

And last not least, in any case, you have to use or call functions (like you noted in the first post), then the work-around I suggested in the last post can help you. In such case, const would be removed.

Good luck :)
Topic archived. No new replies allowed.