перегрузка << операторов и унаследованных классов - PullRequest
9 голосов
/ 07 октября 2011

У меня есть базовый класс, а затем несколько производных классов. Я хотел бы перегрузить оператор «<<» для этих производных классов. Для нормальных операторов, то есть '+', виртуальные функции делают свое дело. Что я понимаю под стандартным соглашением - это объявить </p>

friend ostream& operator<<(ostream& out, MyClass& A);

в моем классе, а затем определите функцию после класса. Априори я бы подумал, что добавление виртуального в приведенное выше определение заставит его работать, но после некоторой мысли (и ошибок моего компилятора) я понимаю, что это не имеет особого смысла.

Я попробовал другую тактику на тестовом примере, где все ученики являются публичными Например:

class Foo{
 //bla
};

ostream& operator<<(ostream& out, Foo& foo){
  cout << "Foo" << endl;
  return foo;
}

class Bar : public Foo{
 //bla
};

ostream& operator<<(ostream& out, Bar& bar){
  cout << "Bar" << endl;
  return bar;
}

///////////////////////

Bar bar = Bar();
cout << bar << endl; // outputs 'Foo', not 'Bar' 

Таким образом, в некотором роде это «полиморфизм испорченный» - вызывается оператор базового класса <<, а не оператор производного класса. В приведенном выше примере, как заставить правильный оператор вызываться для производного класса? И вообще, если в моем классе есть частные члены, которые я хочу защитить, как я могу исправить перегрузку операторов при использовании ключевого слова friend? </p>

Ответы [ 4 ]

6 голосов
/ 07 октября 2011

Вы можете использовать функцию виртуального помощника. Вот полностью непроверенный пример, поэтому извините за любые синтаксические ошибки:

virtual ostream& Foo::print(ostream& out) const {
    return out << "Foo";
}

virtual ostream& Bar::print(ostream& out) const {
    return out << "Bar";
}

// If print is public, this doesn't need to be a friend.
ostream& operator<<(ostream& out, const Foo& foo) {
    return foo.print(out);
}

Редактировать: Очищено за @ Всезнающих предложений.

2 голосов
/ 07 октября 2011

Обычно вы просто создаете полиморфный метод print в базовом классе, который вызывается одной бесплатной функцией-другом.

1 голос
/ 07 октября 2011

С правильными исправлениями кода ваш код работает нормально; ничего не поделаешь :

ostream& operator<<(ostream& out, Foo& foo) {
  out << "Foo" << endl;  // 'out' and not 'cout'
  return out;  // returns 'out' and not 'foo'
}

ostream& operator<<(ostream& out, Bar& bar) {
  out << "Bar" << endl;  // 'out' and not 'cout'
  return out;  // returns 'out' and not 'bar'
}

Демо . Для доступа к private членам вы можете сделать эту функцию как friend в желаемом class.

1 голос
/ 07 октября 2011

Сделать operator<< бесплатной функцией, которая переадресует вызов методу virtual класса Foo.

См. Его в действии .

...