ToanPVN
ToanPVN

Reputation: 31

Inheriting istream operator>>

I have a function in class PhoneNumber:

class PhoneNumber
{
protected:
    int area;
    long number;
public:
    istream& operator>>(istream& is, PhoneNumber &p){
        cout << "Enter area code : ";
        is >> p.area;
        cout << "Enter number telephone number : ";
        is >> p.number;
        return is;
    }
};

and another function in class like this :

class IntPhoneNumber::public PhoneNumber
{
    int reg;
    public 
    friend istream& operator>>(istream& is, IntPhoneNumber &p);
};

I want class IntPhoneNumber to inherit and use operator>> in class PhoneNumber.

Upvotes: 2

Views: 239

Answers (2)

Michael Anderson
Michael Anderson

Reputation: 73530

A nicely scalable way of doing this is to delegate from operator>> to a virtual member function of PhoneNumber, and then provide overloads in derived classes - which can call back into the parent class if they wish.

class PhoneNumber {
protected:
    int area;
    long number;
public:
  friend istream& operator>>(istream& is, PhoneNumber &p);

  virtual void getFromStream(istream& is) {
        cout << "Enter area code : ";
        is >> area;
        cout << "Enter number telephone number : ";
        is >> number;
  }
};

istream& operator>>(istream& is, PhoneNumber &p) {
   p.getFromStream(is);
}

Now you can overload like this:

class IntPhoneNumber::public PhoneNumber {
    int reg;
    virtual void getFromStream(istream& is) {
      PhoneNumber.getFromStream(is);
      cout << "Enter reg :";
      is >> reg;
    }
};

Upvotes: 2

Christophe
Christophe

Reputation: 73446

First you have to declare your extractor as friend:

class PhoneNumber
{
protected:
    int area;
    long number;
public: 
    ...
    friend istream& operator>>(istream& is, PhoneNumber &p);
};

You then defined operator>> outside of the class:

istream& operator>>(istream& is, PhoneNumber &p) 
{
        cout << "Enter area code : ";
        is >> p.area;
        cout << "Enter number telephone number : ";
        is >> p.number;
        return is;

};

Now with this construct already, you could use the same operator>> for the derived IntPhoneNumber, if you wouldn't care for the region code:

struct IntPhoneNumber:public PhoneNumber
{
protected:
    int reg;
public:
    ...
};

This code will compile and handle IntPhoneNumber exactly as PhoneNumber:

PhoneNumber n;
cout<< "Request phone number"<<endl; 
cin >> n;  
cout<< "Request phone int number"<<endl; 
IntPhoneNumber ni; 
cin>>ni; 

Now if you would like to override operator>> for IntPhoneNumber, but reuse what you've already written for PhoneNumber, it's not a problem either. Just define another friend and use casting:

class IntPhoneNumber:public PhoneNumber
{
protected:
    int reg;
public:
    ...
    friend istream& operator>>(istream& is, IntPhoneNumber &p);
};

istream& operator>>(istream& is, IntPhoneNumber &p) 
{
    cout << "Enter area code : ";  // do the specific
    is >> p.reg;
    return is >> static_cast<PhoneNumber&>(p);  // and call the general one
};

Here a live demo on ideone applying this for input and output.

Remark: It's ok for a proof of concept. But normally for an extractor overload (i.e. operator>>) you shouldn't display on cout: if the same extractor would be used for reading data from a file, the screen would be submerged by messages for the user and the reading operation would be slowed down. This is why I've added some if (is==cin) in the live demo.

Upvotes: 1

Related Questions