By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,159 Members | 913 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,159 IT Pros & Developers. It's quick & easy.

inheriting the operator<<

P: n/a
Hi all,

when I write a subclass, can I inherit its superclass' << operator?

As an example say we have two classes, Person and Employee.

class Person has the << operator;

Expand|Select|Wrap|Line Numbers
  1. /**
  2. * Insertion operator
  3. * @param o The output stream to insert a person into
  4. * @param p The person to insert into a stream
  5. */
  6. ostream& operator<<(ostream& o, Person& p)
  7. {
  8. o << p.m_surname << ", " << p.m_firstname;
  9. if (p.m_middlename != "")
  10. o << p.m_middlename;
  11. o << " (" << p.m_dob << ") " << "[";
  12. if (p.m_gender == Person::male)
  13. o << "M";
  14. else if (p.m_gender == Person::female)
  15. o << "F";
  16. else // Shouldn't happen
  17. o << " ";
  18. o << "]";
  19. return o;
  20. }
  21.  
Now in class Employee I want this same behaviour plus some extra
behaviour for the fields which Employee has and Person doesn't;

Expand|Select|Wrap|Line Numbers
  1. /**
  2. * Output to a stream
  3. *
  4. * @param o The output stream to write to
  5. * @param emp The employee to write to an output stream
  6. */
  7. ostream& operator<<(ostream& o, Employee& emp)
  8. {
  9. o= Person::operator<<(o,emp);
  10. o << std::endl << "Started: " << emp.m_startDate
  11. << " Role: " << emp.m_job << "Dept: " << emp.m_department
  12. << std:: endl; << "Salary: " << emp.m_salary << std::endl;
  13. return o;
  14. }
  15.  
I would have thought that since Person::operator() returns an ostream&
that assigning it to the existing o would be ok. However it isn't as
this compiler message informs me;

Expand|Select|Wrap|Line Numbers
  1. operator<< is not a member of Person
  2.  
Now I understand this since it is not a member function as it is
declared as follows;

Expand|Select|Wrap|Line Numbers
  1. friend ostream& operator<<(ostream& o, Person& p);
  2.  
in person.hpp.

So how do I get round this problem? Basically I want to take the
returned ostream& from class Person's operator<< method and insert it
into the ostream& object in class Employee's operator<< method.

Thank,

John

Mar 22 '07 #1
Share this Question
Share on Google+
6 Replies


P: n/a
On Mar 22, 8:54 am, "johnmmcparland" <johnmmcparl...@googlemail.com>
wrote:
Hi all,

when I write a subclass, can I inherit its superclass' << operator?

As an example say we have two classes, Person and Employee.

class Person has the << operator;

[code]
/**
* Insertion operator
* @param o The output stream to insert a person into
* @param p The person to insert into a stream
*/
ostream& operator<<(ostream& o, Person& p)
This operator is not a member. It's an overloaded operator<< that
takes a
Person& as its second argument. (Incidentally, the second parameter
should
probably be declared const.)

ostream& operator<<(ostream& o, Employee& emp)
{
o= Person::operator<<(o,emp);
o << std::endl << "Started: " << emp.m_startDate
<< " Role: " << emp.m_job << "Dept: " << emp.m_department
<< std:: endl; << "Salary: " << emp.m_salary << std::endl;
return o;}
And here you're not *overriding* the base class' operator<< (you can't
override a non-member). You're defining another overloaded operator<<
that
takes an Employee& as its second argument.

In the first statement above you're trying to call the operator<< for
person as if it were a member function. It should be written

operator<<(o, static_cast<Person&>(emp));

or simply,

o << static_cast<Person&>(emp);

Incidentally, you don't need or want to assign the return value of
operator<<
back to o. It doesn't do what you think. operator<< returns a
reference to the
left hand operand so that you can chain the operator as you've done in
the
second statement above. This, the whole function body could be
written:

o << static_cast<Person&>(emp)
<< std::endl << "Started: " << emp.m_startDate
<< " Role: " << emp.m_job << "Dept: " << emp.m_department
<< std:: endl; << "Salary: " << emp.m_salary << std::endl;

Hope this helps.

--Nick

Mar 22 '07 #2

P: n/a
ni*****@microsoft.com wrote:
Incidentally, you don't need or want to assign the return value of
operator<<
back to o. It doesn't do what you think. operator<< returns a
reference to the
left hand operand so that you can chain the operator as you've done in
the
second statement above. This, the whole function body could be
written:

o << static_cast<Person&>(emp)
<< std::endl << "Started: " << emp.m_startDate
<< " Role: " << emp.m_job << "Dept: " << emp.m_department
<< std:: endl; << "Salary: " << emp.m_salary << std::endl;
I agree with everything but the function body. You forgot to return the
ostream ;) like this:

return o
<< static_cast<Person&>(emp)
<< std::endl << "Started: " << emp.m_startDate
<< " Role: " << emp.m_job << "Dept: " << emp.m_department
<< std:: endl; << "Salary: " << emp.m_salary << std::endl;

But I'm sure that was just an oversight.

Cheers!
Adrian
--
__________________________________________________ ___________________
\/Adrian_Hawryluk BSc. - Specialties: UML, OOPD, Real-Time Systems\/
\ _---_ Q. What are you doing here? _---_ /
\ / | A. Just surf'n the net, teaching and | \ /
\__/___\___ learning, learning and teaching. You?_____/___\__/
\/______[blog:__http://adrians-musings.blogspot.com/]______\/
Mar 22 '07 #3

P: n/a
On 22 Mar, 16:59, Adrian Hawryluk <adrian.hawryluk-at-
gmail....@nospam.comwrote:
nikl...@microsoft.com wrote:
Incidentally, you don't need or want to assign the return value of
operator<<
back to o. It doesn't do what you think. operator<< returns a
reference to the
left hand operand so that you can chain the operator as you've done in
the
second statement above. This, the whole function body could be
written:
o << static_cast<Person&>(emp)
<< std::endl << "Started: " << emp.m_startDate
<< " Role: " << emp.m_job << "Dept: " << emp.m_department
<< std:: endl; << "Salary: " << emp.m_salary << std::endl;

I agree with everything but the function body. You forgot to return the
ostream ;) like this:

return o
<< static_cast<Person&>(emp)
<< std::endl << "Started: " << emp.m_startDate
<< " Role: " << emp.m_job << "Dept: " << emp.m_department
<< std:: endl; << "Salary: " << emp.m_salary << std::endl;

But I'm sure that was just an oversight.

Cheers!

Adrian
--
__________________________________________________ ___________________
\/Adrian_Hawryluk BSc. - Specialties: UML, OOPD, Real-Time Systems\/
\ _---_ Q. What are you doing here? _---_ /
\ / | A. Just surf'n the net, teaching and | \ /
\__/___\___ learning, learning and teaching. You?_____/___\__/
\/______[blog:__http://adrians-musings.blogspot.com/]______\/
Thanks Guys. The cast you suggested Nick was what I was looking for.
I had tried a different cast (Java style - (Person)emp) but this had
failed. Maybe its time I re-read my notes on C++ casts.

John

Mar 22 '07 #4

P: n/a
On Mar 22, 11:54 am, "johnmmcparland" <johnmmcparl...@googlemail.com>
wrote:
when I write a subclass, can I inherit its superclass' << operator?
As an example say we have two classes, Person and Employee.
class Person has the << operator;

My way of dealing with this:

class Person
{
// :
virtual void Output(ostream& o) const
{
o << m_surname << ", " << m_firstname;
if (m_middlename != "")
o << m_middlename;
o << " (" << m_dob << ") " << "[";
// etc....
}
};

class Employee : public Person
{
// :
virtual void Output(ostream& o) const
{
Person::Output(o);
o << std::endl << "Started: " << m_startDate
<< " Role: " << m_job << "Dept: " << m_department
<< std:: endl << "Salary: " << m_salary << std::endl;
}
};
template<typename T>
ostream& operator<<(ostream& o, const T& t)
{
t.Output(o);
return o;
}

No ugly casting. Nothing needs to be a friend. Easily Extendable.

Mar 22 '07 #5

P: n/a
johnmmcparland wrote:
Hi all,

when I write a subclass, can I inherit its superclass' << operator?
Yet another alternative:

struct Streamable
{
virtual void output( std::ostream& ) const = 0;
};

std::ostream& operator<<( std::ostream& out,
const Streamable& s ) const
{
s.output( out );
return out;
}

And derive your Person from Streamable.

--
Ian Collins.
Mar 22 '07 #6

P: n/a
On Mar 22, 9:59 am, Adrian Hawryluk <adrian.hawryluk-at-
gmail....@nospam.comwrote:
>
I agree with everything but the function body. You forgot to return the
ostream ;) like this:

return o
<< static_cast<Person&>(emp)
<< std::endl << "Started: " << emp.m_startDate
<< " Role: " << emp.m_job << "Dept: " << emp.m_department
<< std:: endl; << "Salary: " << emp.m_salary << std::endl;

But I'm sure that was just an oversight.
Yep. Thanks for catching it. :-)

Mar 23 '07 #7

This discussion thread is closed

Replies have been disabled for this discussion.