-1

I have seen a few examples of abstract classes with a friend operator<< and a virtual "print" member function where the two declarations are both in the protected section. For example:

class Function{
public:
    virtual ~Function() {} 
    virtual double value(const double x) const = 0;
    virtual Function* clone() const = 0;
protected:
    friend ostream& operator<<(ostream& os, Function& f);
    virtual void print(ostream& os) const = 0;
};

ostream& operator<<(ostream& os, Function& f){
    f.print(os);
    return os;
}

I do not understand why this is mandatory. Can someone explain?

Thanks!

gx_
  • 4,690
  • 24
  • 31
Dan Dv
  • 473
  • 3
  • 12
  • 2
    Why *what* is mandatory? – juanchopanza Jul 28 '13 at 14:21
  • Please learn to write **declaration** correctly... Didn't you notice that [your previous question](http://stackoverflow.com/questions/17907019/friend-declaration-in-protected-section) was edited? (link: http://stackoverflow.com/posts/17907019/revisions) Reading "decleration" makes me sad :'( – gx_ Jul 28 '13 at 15:01
  • Ok I fixed it myself... Now there's still `operator<<`'s parameter `Function& f` that should be `const Function& f` (twice), since printing `f` should _not_ modify it, but I didn't want to touch the code (actually I've just noticed that I added a missing `;` after the class definition). – gx_ Aug 26 '13 at 08:08

2 Answers2

1

First of all, it doesn't matter where you declare the friend function/operator. It isn't public, protected or private. It is just a friend function/operator, so it has access to the class' members, not matter their access restrictions. So the stream operator is not protected. It is a friend, and this allows it to access the print() method.

Second, the print method should probably be private. It would only make sense for it to be protected if you want to call the print method of a base class from a more derived one. But the design suggests that it is an implementation detail in order to implement ostream& operator<<.

If, on the other hand, you designed your class such that it made sense for the print method to be public, there would be no need for the ostream& operator<< to be a friend.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Why should the `print` function be private? Since it is `const`, it can't invalidate any invariants, it has no preconditions, and no post conditions that you could possibly verify. It is, practically, accessible from the public interface via `<<`. I can't think of any possible reason not to make it `public`. – James Kanze Jul 28 '13 at 15:43
  • @JamesKanze I see it as a means to implement the output stream operator `<<`. As such, I saw no need for it in the public interface of the class. – juanchopanza Jul 28 '13 at 15:59
0

It's certainly not mandatory. In fact, I would argue that it is poor design.

Where you put the friend declaration has no importance; access spedifiers don't apply to it. Since the operator<< is part of the public interface, regardless of where you declare it, it makes more sense to declare it in the public area of the class, since that's where users who aren't deriving from the class will look for it.

With regards to the print function, I can also so no real reason for declaring it anything but public. Given that most, if not all accesses to it will be via the friend operator<<, it probably doesn't matter, but I don't see what is gained by declaring it private. And as a general rule, nothing is gained by declaring anything protected; it's very rare to use protected. In the mid 1990s, it was argued that you should declare virtaul functions protected, rather than public, and parts of the standard library still reflect this convention. But I think that the consensus today is that 1) if this rule applies, the virtual functions should be private, not protected, and 2) this rule doesn't always apply—in the case of a const function, like print, it practically never applies.

James Kanze
  • 150,581
  • 18
  • 184
  • 329