Skip to main content
GameDev.net gamedev.net
🔒 Locked

Question regarding compounding operator overloads...

Started by Khaosifix Jan 11, 2005 at 3:55 PM 6 replies 700+ views
Original Post
Khaosifix
Khaosifix
Hello, Out of boredom I decided to make an attempt to code a flexible integer class for fun and learning purposes. One function that I was thinking of raise my concern. I'll show you the source :

class cInteger
{

   int _i ;

 public :

    cInteger() _i(0) { }

    cInteger( int const& p_i ) : _i(0) { }

    cInteger operator<<( ostream& o )
    { // Evidently this isn't flexible at all.

       o << _i ;
       
       return (*this) ;
    }

} ;

ofstream f( "Example.txt" ) ;
cInteger a( 9 ) ;

// These work fine.
a << cout ;
a << fout ;

// What I'm trying to do is compound the two parameters like so :
a << cout << fout ;   // It outputs to the screen successfully but doesn't output to file.

// My other problem is how I would make my class-method more flexible by having it accept 
// a new line, '\n' or endl
// Any suggestions?


---http://www.michaelbolton.comI constantly dream about Michael Bolton.
Khaosifix
Khaosifix
Quote:
Original post by rick_appleton
Aren't you supposed to turn them around?

cout << a << endl;
fout << a << endl;


Not really, since I've declared 'cInteger::operator<<( ostream& o )' I'm able to do :

a << cout ;
a << fout ;

If I've declared something like 'int const& cInteger::c_int() const' then I could do this :

cout << a.c_int() ;
fout << a.c_int() ;
---http://www.michaelbolton.comI constantly dream about Michael Bolton.
desertcube
desertcube
I believe that operator<< should return a reference in order for it to be chained, so try this:
    cInteger & operator<<(ostream & o)    {       o << _i;       return *this;    }


Hope that helps.
Khaosifix
Khaosifix
Quote:
Original post by desertcube
I believe that operator<< should return a reference in order for it to be chained, so try this:
    cInteger & operator<<(ostream & o)    {       o << _i;       return *this;    }


Hope that helps.


The chaining works now but can you explain why returning a reference would allow chaining while a const reference doesn't?

Also how can I overload a newline(ie : endl)
---http://www.michaelbolton.comI constantly dream about Michael Bolton.
desertcube
desertcube
Quote:
Original post by Khaosifix
The chaining works now but can you explain why returning a reference would allow chaining while a const reference doesn't?

Also how can I overload a newline(ie : endl)


A const reference should also work, as long as you make the method const as well.

std::endl is actually a function and ostream has a specially overloaded version of operator<< that takes in functions, something like this:
ostream & operator <<(ostream & (*function)(ostream &)){    return function(*this);}
Oluseyi
Oluseyi
Quote:
The chaining works now but can you explain why returning a reference would allow chaining while a const reference doesn't?
Because your operator << isn't marked const.
const cInteger & operator << (ostream & os) const{  os << _i;  return *this;}
The above code, while horrifically bad form, will work.

Why is it bad form? It's an abuse of a numeric operator by a numeric class for non-numeric purposes, and it's a violation of convention, meaning that it won't be intuitively comprehensible to other programmers. It also uses a leading underscore for an identifier, which the standard reserves for implementation details (of the standard library).

Quote:
Also how can I overload a newline(ie : endl)
endl is an iostream manipulator. It's definition is as follows:
ostream & endl(ostream & os){  os << '\n';  os.flush();  // or os << flush, since flush is another manipulator  return os;}
MaulingMonkey
MaulingMonkey
Quote:
Original post by Oluseyi
Why is it bad form? It's an abuse of a numeric operator by a numeric class for non-numeric purposes, and it's a violation of convention, meaning that it won't be intuitively comprehensible to other programmers. It also uses a leading underscore for an identifier, which the standard reserves for implementation details (of the standard library).


Err, IIRC actually only an underscore followed by an uppercase letter is reserved for library implementors.

I should also note that the use of operator<< in this context is not only a violation of numeric principles, but also exactly counterintuitive to what anyone who has used the standard iostream library will expect:

the iostream way:

ostream << variable; //"Put the variable into the ostream"
istream >> variable; //"Take the variable out of the istream"

your way:
variable << ostream; //"Put the ostream into the variable"
variable >> istream; //"Put the istream into the variable"

What you want to do, more likely, is the following:

ostream & operator<< ( ostream & , cInteger );class cInteger{    friend ostream & operator<< ( ostream & , cInteger );    //...};ostream & operator<< ( ostream & out , cInteger i ){    out << i._i;    return out;};


which allows for this somewhat useful chaining:

cout << a << "pie" << b;

instead of your whacked out chaining:

a << cout << cerr << clog << cout;

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.