C++ Inheritance and Friend Operators Question

Over the last year I’ve gotten a lot of benefit out of my effort to move to C++. Classes rock!

However, I now am at a point where I don’t understand how the language works, and I’m having trouble finding references to explain. I’m not looking for suggestions of languages that do it better for this; I simply would like an explanation/pointer to information/search term that tells me what to google for in the following issue:

I have a base class and a derived class. The only difference in the derived class is that it has an additional data member and functions which help to access that data member. The important part of my code is as follows:


class Base
{
  private:
    string Str;
    double A;
  public:
    // ...
   friend std::istream& operator>>(std::istream &In, Base &BaseIn)
  {
    In >> Str >> A;
    return In;
  }
};

class Derived:Base
{
  private:
    double B;
  public:
  // ...
  friend std::istream& operator>>(std::istream &In, Derived &DerivedIn)
 {
 -->  In >> Str >> A >> B;
   return In;
  }
};

The problem I’m having is that if I understand correctly, I can’t override the input operator for the derived class in that way, because I don’t have access to Str and A within the Derived class since they’re private. I could declare them protected to get around this, I believe. Is that the “proper” way to manage this problem? If so it tends to imply that I’ll always need to make base classes protected instead of private, which leads to the question of why does private work the way it does for inherited classes in the first place.

Since I don’t believe they’d have an entire useless provision for data protection (private vs. protected), I’m guessing I’m missing something. I know I can set up functions in the base class that let me manipulate the member data from an external interface and change the overloaded input operator in the derived class to work that way:


class Base
{
  private:
   // ... See Above
  public:
    Base& SetStr(const string& _Str) { Str = _Str; return *this; }
    Base& SetA(const double& _A) { A = _A; return*this; }
  //...
};

  class Derived:Base
{
  private:
    double B;
  public:
   // ...
   friend std::istream& operator>>(std::istream &In, Derived &DerivedIn)
  {
     string Str;
     double A;
     double _B;
     In >> Str >> A >> _B;
     DerivedIn.SetStr(Str);
     DerivedIn.SetA(A);
     B=_B;
     return In;
  }
};

However that seems needlessly complex. Is this the proper way? Will this work at all?

Ultimately it feels like it ought to work something like this:


class Derived:Base
{
  public:
    // ...
  private:
    // ...

  friend std::istream& operator>>(std::istream &In, Derived &DerivedIn)
  {
    In Base::operator>> DerivedIn >> B;
    return In;
  }
};

i.e. I should be able to explicitly call the Base version of the input operator >> .

This is how it would work if it were a regular function (Derived::Fn() --> Base::Fn() + excess Fn() processing specific to Derived), but because operator>> is a bit weird I’m not sure I totally understand it and what it actually binds to. (Generally things like Class::Operator+ bind to the lhs, which would imply that what I’d need in the above example would be istream::operator>>, but of course that lhs + operator can’t differentiate between what I’m spitting data into, so that can’t be the answer either.)

Hopefully this somewhat muddled question makes sense to someone out there? I’m fine to do the research if it’s as complex as I’m afraid it might be (Stroustrup’s book gives a great example of calling, say, Base::print() from Derived::print() to operate with the base class’s defined functions, but the istream input operator seems to be logically different here…) if someone can just point me to the proper term for research.

Thanks in advance!

If a member needs to be accessed directly in derived classes, then it should indeed be declared as protected instead of private. The difference between private and protected is largely in where the member is intended to be used. If a member is common to all derived classes, but is manipulated in different ways in each derived class, you can make it protected in the base class instead of declaring it separately in every derived class. That lets you do common operations on it in the base class, too.

Using accessors or nesting the operators will work too, but looks rather awkward and may expose more than you really want (if it’s truly internal, then you don’t really want public accessors letting anybody mess with it willy-nilly).

I’m always dumbfounded anew by how C++'s inheritance model is a mess when I see questions like this.

In case you haven’t seen it, the Parashift C++ FAQ has just about everything you’d need on something like this. In this case, the inheritance topic goes into scenarios for protected, is-a vs. has-as, etc.

Friends are really just an implementation hack; weren’t they added specifically for operators or something?

I don’t know about their intended use (my copy of Stroustrup is at the office), but that’s about all I can remember using friends for. In this case you have to use them to follow the stream chaining convention without being able to alter the stream class.

Also, after messing with it a bit, it looks like the syntax for nesting the operators to get at A isn’t actually that bad, if you want to keep everything private. It remains clear enough what you’re intending to do:

class Derived: Base
{
    private:
        double B;
    public:
        friend std::istream& operator>>(std::istream &In, Derived &DerivedIn)
        {
            In >> (Base&)DerivedIn >> DerivedIn.B;
            return In;
        }
};

Hey, that’s not bad at all and in line with what I suspected should be possible. Thanks fugitive! (I’m probably now committing myself to some subtle bug that will persist for years, but, hey, that’s job security right! ;) )