cout operator overloading

This is a discussion on cout operator overloading within the C++ Programming forums, part of the General Programming Boards category; Hi, My background is mostly in Java, but I've done some C++ a long time ago. I've been searching most ...

  1. #1
    Registered User
    Join Date
    Oct 2006
    Posts
    2

    cout operator overloading

    Hi,

    My background is mostly in Java, but I've done some C++ a long time ago.

    I've been searching most of the afternoon to figure out the difference between the 3 ways of printing out a message below, all sites I've found say that they're all equivalent, but the output below doesn't support that:

    Code:
    int main(int argc, char** argv) {
        char* message = "Test";
        
        cout << message;
        cout << endl;
        
        operator <<(cout, message);
        cout << endl;
        
        cout.operator <<(message);
        cout << endl;
        
        return 0;
    }
    And the output is:

    Code:
    Test
    Test
    0x443000
    Why does the
    Code:
    cout.operator <<(message)
    print out the address and not the message?

    Thanks.

    Bob

  2. #2
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,262
    Sure it's printing the address?
    Code:
    int main(int argc, char** argv) {
        char* message = "Test";
        
        cout << &message;
        cout << endl;
        
    	cout.operator <<(message);
        cout << endl;
    	
        cout << &message;
        cout << endl;
        
        return 0;
    }

  3. #3
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,435
    To understand why this happens you need to read about the cout object more closely.

    cout is an object of the ostream class. Among it's member functions there are a series of overloaded << operators. Among them, this one:

    Code:
    ostream& operator<<(char);
    When you write cout.operator <<(message) what are you returning according to that function?... you are returning a reference to an ostream object. You are returning a reference to cout itself.

    This is expected behavior and is what allows chaining of cout statements.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    2
    Thanks for the replies so far, but I may not have been clear enough.

    twomers, I know it prints the address, that's the problem. Most sites state that:
    Code:
    cout << message;
    and
    Code:
    cout.operator <<(message);
    are equivalent, but the code I posted doesn't print out the same thing, the first prints out the message as expected, but the second prints out the address of the message.

    Mario F., I understand about method chaining, it's used alot in Java also. What I'm not sure about is:

    Why are the above two statements not equivalent? (To me, it would seem they should, but apparently not)

    And instead of
    Code:
    ostream& operator<<(char);
    wouldn't it use
    Code:
    ostream& operator<<(void*& val);
    since we're passing in a char*?

    Anyone have a good C++ reference besides http://www.cplusplus.com/?

    Thanks.

    Bob

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,435
    Actually you just nailed it. I had to look because I didn't know what overloads there where for cout. char anyways would never be the one. As you say, your variable is of type char*.

    ostream& operator<<(void*& val); is indeed the one that will be used (if I understand the rules of implicit conversion correctly). And this is exactly why you are experiencing this problem.

    Think about it. You will no longer have a char* when this overload is selected. You will have a reference to a pointer to void. What can do cout with this? Not much. a void pointer can't be used to refer to the object it points to. It will have to be cast back first. But obviously the overloaded function will not do this cast. it has no knowledge of the original type.

    So effectively there was an implicit conversion and this is one damn good reason not to use the cout.operator() form for non overloaded types.
    Last edited by Mario F.; 10-02-2006 at 08:15 PM.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,262
    My point was that

    Code:
    cout<< &message;
    cout<< endl;    
    cout.operator<< ( message );
    print two different things, which suggests that the latter doesn't print the address of message, rather a 'reference to an ostream object [...] a reference to cout itself'. I don't pretend that I knew the answer Mario gave, but I was pretty sure it wasn't the address of message that the cout.operator<<() was printing, so it could only be something to do with cout

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    twomers: the first prints the address of the char* pointer, the second the value of the char* pointer, i.e. the address of the string.

    In short, all the sites that claim equivalency are quite simply wrong. Using an operator overloading function directly and using the overloaded operator are not equivalent, simply because there are two ways of overloading most operators, and only using the operator automatically chooses between them. Directly calling the function when in reality, the operator is implemented the other way round, leads to compile errors if you're lucky, and to unexpected results in this particular case, because there are so many overloads of <<.

    In other words, cout itself contains this member function:
    Code:
    class basic_ostream {
      // ...
      self_type &operator <<(const void *); // Prints an address
    };
    In addition, there is this free function also overloading <<: (omitting template stuff for clarity)
    Code:
    ostream & operator <<(ostream &s, const char *sz); // Prints the string
    Now, let's check it out.
    Code:
    const char *strlit = "Hello, World!";
    
    cout << strlit; // 1
    operator<<(cout, strlit); // 2
    cout.operator<<(strlit); // 3
    1) Here the overloaded operator is used. The compiler collects all functions that overload << and finds these (among many others which are not relevant):
    ostream::operator<<(const void*)
    operator<<(ostream&, const char*)
    The call signature is
    (ostream lvalue) << (const char* lvalue)
    It chooses the function that most closely fits the supplied types, which is the free function. So you get the string.

    2) Here, you explicitely call a free function called operator<<. So the compiler collects all free functions by that name. It might, for example, find these:
    operator<<(ostream&, const char*)
    operator<<(ostream&, const string&)
    operator<<(ostream&, const complex&)
    The call signature is
    operator<<(ostream lvalue, const char* lvalue)
    Again, the compiler chooses the const char* variant as the best fit.

    3) This time, you request a member of ostream by the name of operator<<. The compiler again collects the overload set, which contains among others these:
    ostream::operator<<(int)
    ostream::operator<<(double)
    ostream::operator<<(const void*)
    The call signature is
    (ostream lvalue) . ostream::operator<<(const char* lvalue)
    No direct match this time, so the conversions are considered. The simplest conversion (in fact, in this overload set, the only possible one) turns out to be the const void* one, so it is chosen.

    As you can see, they're not at all equivalent.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. class methods to cout stream
    By shintaro in forum C++ Programming
    Replies: 5
    Last Post: 11-11-2008, 06:27 PM
  2. cout
    By RenderedAwake in forum C++ Programming
    Replies: 5
    Last Post: 02-03-2005, 06:14 AM
  3. How Does cout Work
    By jrahhali in forum C++ Programming
    Replies: 8
    Last Post: 08-25-2004, 03:19 PM
  4. cout vs std::cout
    By none in forum C++ Programming
    Replies: 10
    Last Post: 07-26-2004, 11:20 PM
  5. FAQ cout
    By evilmonkey in forum FAQ Board
    Replies: 1
    Last Post: 10-07-2001, 11:32 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21