оператор‹‹ в производных классах С++

у меня есть вопрос к оператору << в производных классах, например:

если бы у меня был

class Base
{
      //......
      friend ostream& operator<<(ostream& out,Base &B)
      {
          return  out<<B.x<<B.y<</*........*/<<endl;
      }
      //......    
};

возможно ли следующее?

class Derived: public Base
{
       //......
       friend ostream& operator<<(ostream& out,Derived &DERIVEDOBJECT)
       {
           return  out<<DERIVEDOBJECT<<DERIVEDOBJECT.nonderivedvar1 <</*.....*/<< endl;
       }
}

или добавление DERIVEDOBJECT в оператор << не приведет к тому, что << распознает его как ссылку только на базовый класс?


person Aleksandar    schedule 20.04.2011    source источник
comment
@Aleksander — используйте 4 пробела перед каждым оператором кода или просто используйте {}, который присутствует в окне редактора для форматирования кода.   -  person Mahesh    schedule 21.04.2011


Ответы (3)


Обычно вы хотите что-то вроде этого:

class Base { 

     virtual std::ostream &write(std::ostream &os) { 
         // write *this to stream
         return os;
     }
};

std::ostream &operator<<(std::ostream &os, Base const &b) { 
     return b.write(os); 
}

Затем производный класс переопределяет write, когда/если это необходимо.

person Jerry Coffin    schedule 20.04.2011
comment
+1: В конце концов, вероятно, лучше иметь определенную функцию записи. - person Martin York; 21.04.2011
comment
Я думаю, что b.write не будет вызывать виртуальную функцию, потому что это не вызов по указателю. - person Giovanni Funchal; 21.04.2011
comment
@Giovanni: Полиморфизм в C++ работает со ссылками так же хорошо, как и с указателями. - person Fred Larson; 21.04.2011
comment
Ах да, ссылку не увидел (обычно пишу const Base& b, а не Base const &b). - person Giovanni Funchal; 21.04.2011

Это вызовет рекурсивный вызов:

out<<DERIVEDOBJECT

Я бы сделал:

   friend ostream& operator(ostream& out,Derived &DERIVEDOBJECT)
   {
       return  out << static_cast<Base&>(DERIVEDOBJECT)
                   << DERIVEDOBJECT.nonderivedvar1
                   <<.....<< endl;
   }

PS. Пробелы и строчные буквы — ваши друзья.
По соглашению идентификаторы, которые все в верхнем регистре, являются макросами, поэтому вы можете запутать людей, используя все идентификаторы в верхнем регистре для обычных переменных.

person Martin York    schedule 20.04.2011
comment
+1 за разговор о переменных в нижнем регистре. ЭТО БОЛЬНО МОИМ ГЛАЗАМ :-) - person Giovanni Funchal; 21.04.2011

Вы можете добиться ожидаемого результата, преобразовав в базовый тип:

struct base {};
std::ostream& operator<<( std::ostream& o, base const & b ) {
   return o << "base";
};
struct derived : base {};
std::ostream& operator<<( std::ostream& o, derived const & d ) {
   return o << static_cast<base&>(d) << " derived";
}
int main() {
   derived d;
   std::cout << d << std::endl; // "base derived"
}
person David Rodríguez - dribeas    schedule 20.04.2011