Thread: A treatise on friend is needed

  1. #16
    Registered User
    Join Date
    Dec 2012
    Posts
    45
    Quote Originally Posted by manasij7479 View Post
    Well, overloading stream operators often need the declarations to be 'friendly'.
    I have seen that example in a lot of places, so I think it is not evil™.
    In these cases I prefer to implement the functionality in a public method (virtual, most of the times). The operator << receives a reference to the object and calls the virtual method.

  2. #17
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by comocomocomo View Post
    In these cases I prefer to implement the functionality in a public method (virtual, most of the times). The operator << receives a reference to the object and calls the virtual method.
    Neat idea!
    Though that makes the overloading somewhat pointless, as you could ( and probably should, to avoid large copy operations ) just
    use that member function to plug its string/stream output to the stream <</>> was to be called with.

  3. #18
    Registered User
    Join Date
    Dec 2012
    Posts
    45
    Quote Originally Posted by manasij7479 View Post
    Neat idea!
    Though that makes the overloading somewhat pointless, as you could ( and probably should, to avoid large copy operations ) just
    use that member function to plug its string/stream output to the stream <</>> was to be called with.
    I think it's the other way around. If everything is passed by reference, my design requires no copy operations. If you put the text in a std::string and then pass it to the op<< for strings, you create a temporary copy of the data: the string itself!

    Code:
    #include <iostream>
    
    
    class A
    {
        public:
        
            virtual void print (std::ostream & os) const
            { os << "Object of class A" << std::endl; }
            
            virtual ~A () {}
    };
    
    
    inline std::ostream & operator<< (std::ostream & os,
                                      const A & a)
    {
        a.print (os);
        return os;
    }
    
    
    class B : public A
    {
        public:
        
            virtual void print (std::ostream & os) const
            { os << "Object of class B" << std::endl; }
    };
    
    
    using namespace std;
    
    
    int main ()
    {
        A * p, * q;  // Note: both are pointers to A
        
        p = new A;   // Object of base class
        q = new B;   // Object of derived class
        
        cout << *p   // Prints: "Object of class A"
             << *q   // Prints: "Object of class B"
             << endl;
    
    
        delete p;
        delete q;    
        return 0;
    }
    The clients are supposed to call the operator<< and not the method print(). The point is: do we care? There is no integrity issue. The only problem is that the public interface is bloated with one more name. If you think this is too bad, make print() private and 'friend' the operator<<. I usually don't.

  4. #19
    Registered User
    Join Date
    Dec 2012
    Posts
    45
    Oh, and you might want B's print() to show the inherited part of the object by calling A's print():

    Code:
    class B : public A
    {
        public:
    
            virtual void print (std::ostream & os) const
            {
                 os << "Object of class B. Base: ";
                 A::print (os);
            }
    //...
    In this case, if you decide to hide print() from the clients, you would have to make it protected, not private.

    If I leave print() public, you might argue that my operator<< is just syntax sugar, but... yum! :-)
    Last edited by comocomocomo; 01-02-2013 at 09:11 AM. Reason: Remove unintended smileys

  5. #20
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I don't see the importance of inheritance here at all. You still write two methods to call through yet another method....

  6. #21
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by whiteflags
    I don't see the importance of inheritance here at all. You still write two methods to call through yet another method....
    That is fine because the overloaded operator<< cannot be a virtual member function, so making use of a virtual print function is normal. If you want, you can keep only the overloaded operator<< as the public interface by declaring it as a friend of the base class, then having the virtual print function be private (or at least protected), i.e., implement the non-virtual interface idiom.

    Of course, this only makes sense if inheritance is used, otherwise it would be unnecessary work, hence comocomocomo's preference betrays a possible overuse of inheritance
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #22
    Registered User
    Join Date
    Dec 2012
    Posts
    45
    Quote Originally Posted by whiteflags View Post
    I don't see the importance of inheritance here at all. You still write two methods to call through yet another method....
    You are right. I included inheritance in an attempt to address the most general case.

    When using inheritance, you just need to write the operator<< once. I find this fact very interesting. That's all.

  8. #23
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by comocomocomo
    When using inheritance, you just need to write the operator<< once. I find this fact very interesting.
    Dunno, I don't find that terribly interesting: when not using inheritance, you also just need to write the operator<< once. In my opinion, the main advantage of using a print member function is that it can be virtual, and in fact the typical reason for having a print member function in addition to operator<< is that it is virtual.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #24
    Registered User
    Join Date
    Dec 2012
    Posts
    45
    I'm reading Scott Meyers' "Effective C++, 3rd edition". I'm still with item 19, but I followed some cross references and ended up in item 46: "Define non-member functions inside templates when type conversions are desired". The title does not mention it, but the trick suggested requires the use of 'friend'.

    Basically, we have a class that should behave as a number (complex, rational... whatever). We define operator overloads (sum, product..) outside the class because we want automatic type conversions on both parameters.

    Then we tempatise the whole design. The class becomes a template. The external operators become templates too. And then the automatic conversions don't work anymore!

    The compiler won't try to cast the parameters to the template instantiation because it still hasn't decided which template instace to use.

    The solution: 'friend' the desired operators instantiation from within the class template. The purpose is not letting them access the internals, but have them declared (or should I say instantiated...).

    Isn't it amazing.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Helping out a friend...
    By rhymewithnothin in forum C Programming
    Replies: 21
    Last Post: 09-15-2005, 08:59 PM
  2. for a friend
    By Ajsan in forum C++ Programming
    Replies: 4
    Last Post: 02-25-2004, 11:04 AM
  3. friend function and friend classes...usage question??
    By actionbasti in forum C++ Programming
    Replies: 2
    Last Post: 10-30-2003, 10:53 PM
  4. friend
    By laasunde in forum C++ Programming
    Replies: 3
    Last Post: 11-30-2002, 10:15 AM