Наследование оператора istream >>

У меня есть функция в классе 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;
    }
};

и еще одна функция в классе, как это:

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

Я хочу класс IntPhoneNumber наследовать и использовать operator>> в классе PhoneNumber,

2 ответа

Хорошо масштабируемый способ сделать это - делегировать от operator>> к функции виртуального члена PhoneNumberи затем предоставьте перегрузки в производных классах - которые могут перезвонить в родительский класс, если они захотят.

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);
}

Теперь вы можете перегрузить вот так:

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

Сначала вы должны объявить своего экстрактора как друга:

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

Вы тогда определили operator>> вне класса:

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

};

Теперь с этой конструкцией вы можете использовать тот же operator>> для производного IntPhoneNumber, если вас не интересует код региона:

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

Этот код будет скомпилирован и обработан IntPhoneNumber именно так PhoneNumber:

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

Теперь, если вы хотите переопределить оператор >> для IntPhoneNumber, но повторно используйте то, что вы уже написали для PhoneNumber, это тоже не проблема. Просто определите другого друга и используйте кастинг:

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
};

Вот живая демонстрация на ideone, применяющем это для ввода и вывода.

Замечание: это нормально для доказательства концепции. Но обычно для перегрузки экстрактора (т.е. operator>>) вы не должны отображаться на cout: если тот же экстрактор будет использоваться для чтения данных из файла, экран будет погружен сообщениями для пользователя, и операция чтения будет замедлена. Вот почему я добавилif (is==cin) в живом демо.

Другие вопросы по тегам