question regarding operator << overloading

G

Goran

Hi all,

I have a question regarding operator <<.

A lib of mine contains a class with an overloaded operator << as NON-
class member. This would look like:


#include <iostream>
#include <libsomelib.h>

using namespace std;
using namespace SOMELIB;

int main() {

myClass_t myObject;

cout << myObject;

return 0;
}


The example above works fine. But now I'm building a second lib with
newClass_t and myClass_t as private member:


#include <ostream>
#include <libsomelib.h>

class newClass_t {

public:
...
myClass_t GetMyClass() const;
private:
myClass_t itsMyClass;
}

&ostream operator <<(ostream&, const newClass_t&)


The source file:


...

ostream& <<(ostream& aStream, const newClass_t& aNewClass) {

aStream << aNewClass.GetMyClass();

return aStream;
}


OK, now there is a problem. It's the line "aStream <<
aNewClass.GetMyClass();". It does not compile. The error: no match for
»operator<<« in »aStream << newClass_t::GetMyClass()

So the compiler can't find the overloaded operator. Why? It's inside
libsomelib.h. What's wrong?

Thanks for answering
 
G

Goran

[...]
You didn't say how your operator<< is declared. It might matter.
[...]

You're right. Here is a new example:

This main() works...

#include ...

using namespace std;
using namespace SOMELIB;

int main() {

myClass_t myObject;

cout << myObject;

return 0;

}

Because next lib works too:

using namespace std;

namespace SOMELIB {

class myClass_t {
...
};
ostream& operator <<(ostream&, const myClass_t&);
}


Now I want to build a new lib...

#include <ostream>
#include <libsomelib.h>

using namespace std;
using namespace SOMELIB;

namespace NEWLIB {

class newClass_t {

public:
...
void AddMyClass(const myClass_t&);
myClass_t GetMyClass() const;
private:
myClass_t itsMyClass;
};
ostream& operator <<(ostream&, const newClass_t&);
}

newClass_t works also fine but one problem! If I use the operator <<
from myClass_t inside the operator << definition from newClass_t I
got the error. The definition looks like:

ostream&
NEWLIB::
operator <<(ostream& aStream, const newClass_t& aNewClass) {

// Here comes the error!
aStream << aNewClass.GetMyClass();

return aStream;
}
 
G

Goran

// You are right! I'm a lazy dude :D. Here's a correct example which
does not
// compile! The error:
// main.c++: In function »std::eek:stream&
BADLIB::eek:perator<<(std::eek:stream&, BADLIB::BadClass_t&)«:
// main.c++:110: Error: no match for »operator<<« in »aStream <<
BADLIB::BadClass_t::GetValue() const()«

#include <iostream>
#include <string>
#include <ostream>




//// START GOOD CLASS ////

// The GoodClass_t is nothing special but the overloaded operator <<.
// The operator calls the method SetMode and GetMode to change the
output.
using namespace std;

namespace GOODLIB {

class GoodClass_t {

public:
GoodClass_t();
string GetValue() const;
void SetMode(const bool&);
bool GetMode() const;
private:
string itsValue;
bool itsMode;
};
// this operator works
ostream& operator <<(ostream&, GoodClass_t&);
}

GOODLIB::
GoodClass_t::
GoodClass_t() {

itsValue = "foo";
itsMode = true;
}

string
GOODLIB::
GoodClass_t::
GetValue() const {

return itsValue;
}

bool
GOODLIB::
GoodClass_t::
GetMode() const {

return itsMode;
}

void
GOODLIB::
GoodClass_t::
SetMode(const bool& aMode) {

itsMode = aMode;
}

ostream&
GOODLIB::
operator <<(ostream& aStream, GoodClass_t& aWC) {

if(aWC.GetMode()) {
aWC.SetMode(false);
aStream << "Begin Opening (" << aWC.GetValue() << ") End Opening
\n";
}
else {
aWC.SetMode(true);
aStream << "Begin Closing (" << aWC.GetValue() << ") End Closing
\n";
}

return aStream;
}
//// END GOOD CLASS ////




//// START BAD CLASS////

// The BadClass_t contains a private GoodClass_t Object available by
// GetValue(). So it's very simple. But in conjunction with
GoodClass_t I
// really don't know where's the failure.
using namespace std;
using namespace GOODLIB;

namespace BADLIB {

class BadClass_t {

public:
BadClass_t(const GoodClass_t&);
GoodClass_t GetValue() const;
private:
GoodClass_t itsGoodObj;
};
ostream& operator <<(ostream&, /* const */ BadClass_t&);
}

BADLIB::
BadClass_t::
BadClass_t(const GoodClass_t& aGoodObj)
: itsGoodObj(aGoodObj) {

}

GoodClass_t
BADLIB::
BadClass_t::
GetValue() const {

return itsGoodObj;
}

ostream&
BADLIB::
operator <<(ostream& aStream, /* const */ BadClass_t& aBC) {

aStream << aBC.GetValue() << "\nsome stuff\n" << aBC.GetValue();
}
//// END BAD CLASS////


using namespace std;
using namespace GOODLIB;
using namespace BADLIB;

int main() {

GoodClass_t aGoodObj;
BadClass_t aBadObj(aGoodObj);

// Begin Opening (foo) End Opening
// Begin Closing (foo) End Closing
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cout << aGoodObj << aGoodObj; // Works fine

cout << aBadObj; // BAD!!! WHY???

return 0;
}
 
G

Goran

First... thanks for your detailed description, Victor!

Regarding your questions:
[...]
It would be also good to know which line is 110, don't you think?
[...]
The Line 110 is:
aStream << aBC.GetValue() << "\nsome stuff\n" << aBC.GetValue();


[...]
Note that 'GoodClass_t' object is *non-const*. Is there a reason
why this is so?
[...]
This is due to the fact that a private member is changed.

[...]
So, while *outputting* an object you *set* its mode? I don't know.
Does not seem like a good idea. Anyway...
[...]
Yeah, because there are two ways of output. E.g. Line 110.

I hope answered all questions. Your analyze below is instructive.
[...]
ostream&
BADLIB::
operator <<(ostream& aStream, /* const */ BadClass_t& aBC) {
aStream << aBC.GetValue() << "\nsome stuff\n" << aBC.GetValue();

So, let's examine this. 'aBC.GetValue()' returns a temporary,
which you try to pass to the op<< that expects an lvalue. The
argument of the op<< is a reference to non-const that cannot be
bound to a temporary.

You need to revise your interface.
[...]
I will do so.

Greetings, Goran
 
F

Frank Birbacher

Hi!

Victor said:
I think what you're saying here is that you need the *alternating* way
of outputting each object. I've never has the need to do that with any
of my objects, but I concede there may be a need. I would, however, in
that case define the 'mode' a *mutable* member of your class and make
'SetMode' a const member and declare the 'aWC' argument a reference to
*const* object.

Or you create two separate output functions (not operator <<) and a
separate function object with external state. I'm afraid keeping the
output mode in the object is not reentrant.


Well, Goran, first try the mutable concept.

Frank
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,930
Messages
2,570,072
Members
46,522
Latest member
Mad-Ram

Latest Threads

Top