4

I am refreshing cpp after a long gap, trying to understand the operator overloading methods. I tried to overload "operator<<" to output members of object. but I am unable to do so without using friend function. I am looking for a method without using friend function.

here is my class def:

class Add{
private:
int x;

public:
friend ostream& operator<<(ostream& ostr, Add const& rhs); //Method 1
void operator<<(ostream& ostr);                //Method 2
};

functions implementations

//Method 1
ostream& operator<<(ostream &ostr, Add const& rhs)
{
    ostr<<rhs.x;

return ostr;
}

//Method 2
void Add::operator<<(ostream& ostr)
{
    cout<<" using operator<< \n";
    ostr<<x;
}

calls from the main function

cout<<Obj_Add;  //calls the Method 1

Obj_Add<<cout;  //calls the Method 2

Now my question is, I would like to achieve the Method 1 type calls without using the friend function. But do not know, it is possible or not in cpp. I have tried few implementation but all are gives me compile errors. Please help me to understand the point i'm missing here.

Flexo
  • 87,323
  • 22
  • 191
  • 272
chinnagaja
  • 155
  • 2
  • 4
  • 14
  • 3
    What's the reason for wanting to avoid friend functions for this? – NPE Jan 11 '12 at 12:30
  • @aix: Always prefer non-member, non-friend functions for additional operations. The smaller your interface into the real world, the lesser the places you have to worry about when changing something. – Xeo Jan 11 '12 at 12:34
  • Xeo: *non member, non friend* discards both alternatives, so aix's question still stands: why? This is precisely the reason for friendship in the first place. – David Rodríguez - dribeas Jan 11 '12 at 12:52
  • @aix: if we remove friend, the compiler want the function to be decleared with one parameter eventhough it is in public to class. Why this restriction? – chinnagaja Jan 11 '12 at 12:52
  • @chinnagaja: Are you aware that a `friend` declaration declares a non-member function? This means that if you remove `friend` you must also move the declaration outside of the class body to keep the meaning of the declaration the same. – CB Bailey Jan 11 '12 at 13:40
  • @charles: yes i understood the friend rules. But I would like to know why the compiler is not accepting a operator overload function with two arguments instead of 'this' with one argument. – chinnagaja Jan 11 '12 at 13:50
  • this answer clarifies me more clearly. for your Ref. http://www.parashift.com/c++-faq-lite/friends.html#faq-14.2 – chinnagaja Feb 01 '12 at 11:22

4 Answers4

5

If you have public accessor functions in your class, or a stream-like one, you don't need the friendship with operator<<:

// v1
class foo{
public:
  int data() const{ return _data; }
private:
  int _data;
};

std::ostream& operator<<(std::ostream& o, foo const& f){
  return o << f.data();
}

// v2
class foo{
public:
  void stream_to(std::ostream& o){
    o << _data;
  }
private:
  int _data;
};

std::ostream& operator<<(std::ostream& o, foo const& f){
  f.stream_to(o);
  return o;
}

v2 has the added benefit of allowing stream_to to be a virtual function, which is helpful for polymorphic base-classes, so you don't need to reimplement operator<< for every derived class, only stream_to.

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • 1
    I would avoid the first option: opening the implementation details to *all* code to avoid opening access to *one* friend is not such a good idea (it could be worse, making the field public, but the fact that it is not the worst alternative does not make it the *best* option) – David Rodríguez - dribeas Jan 11 '12 at 12:55
  • @David: Well, I only adhered to the "client"'s specifications: no friends. ;) – Xeo Jan 11 '12 at 12:58
  • v2 seems a good option. but without friend we cannot achieve cout< – chinnagaja Jan 12 '12 at 19:58
  • @chinnagaja: What exactly do you mean? You can call `std::cout << my_foo;` just fine with both versions. – Xeo Jan 12 '12 at 19:59
  • @Xeo: yes I agree. but the function is not a member function of foo. if you make it as member in public the compiler throws error. how to achieve this call to a member function of foo. I feel method-2 in my question is safe than friend or non-member function but call to that function is should be in reverse order (obj< – chinnagaja Jan 13 '12 at 09:15
  • 1
    @chinnagaja: You can't. If you make `operator<<` a member function, then the left-hand side (`X` in `X << Y`) needs to be of your class type. That's why it needs to be a free function (possibly a friend). How would you possibly distinguish between `X << Y` and `Y << X`, where `X` is your class type? – Xeo Jan 13 '12 at 09:56
  • @xeo: now I understood the need of free or friend func in operator<< if we use other than our class objects (cout). Thanks for helping me to understand. – chinnagaja Jan 26 '12 at 12:27
  • @Xeo: Why reference to ostream is passed when overloading << operator? Why I can't write (ostream o,foo const & f in the argument? – Destructor May 14 '15 at 04:11
2

It's possible with a getter of x.

if the operator<< is not friend, it can not access the member x

class Add {
    private:
        int x;

    public:
        int getX() { return x; }
};

//Method 1
ostream& operator<<(ostream &ostr, Add const& rhs)
{
    //ostr<<rhs.x;       //Fail: x is private

    ostr << rhs.getX();  //Good

    return ostr;
}
BAK
  • 972
  • 8
  • 23
1

You can avoid having the operator function as friend if you have some other means of getting x from the object.

class Foo
{
private:
    int bar;

public:
    int get_bar() const { return bar; }
};

ostream &operator<<(ostream &os, const Foo &foo)
{
    os << foo.get_bar();
    return os;
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

This is not possible unless you add some mechanism to get x out, e.g. a public

// in the class
int get_x() const { return x; }

or a different mechanism to print an object

// outside the class
std::ostream &operator<<(std::ostream &out, Add const &obj)
{
    obj.print(out);
    return out;
}
Fred Foo
  • 355,277
  • 75
  • 744
  • 836