Наследование оператора 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)
в живом демо.