Connecting Tech Pros Worldwide Help | Site Map
 
 
LinkBack Thread Tools Search this Thread
  #1  
Old March 22nd, 2007, 04:55 PM
johnmmcparland
Guest
 
Posts: n/a
Default inheriting the operator<<

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

  #2  
Old March 22nd, 2007, 05:45 PM
niklasb@microsoft.com
Guest
 
Posts: n/a
Default Re: inheriting the operator<<

On Mar 22, 8:54 am, "johnmmcparland" <johnmmcparl...@googlemail.com>
wrote:
Quote:
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.)

Quote:
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

  #3  
Old March 22nd, 2007, 06:05 PM
Adrian Hawryluk
Guest
 
Posts: n/a
Default Re: inheriting the operator<<

niklasb@microsoft.com wrote:
Quote:
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/]______\/
  #4  
Old March 22nd, 2007, 06:45 PM
johnmmcparland
Guest
 
Posts: n/a
Default Re: inheriting the operator<<

On 22 Mar, 16:59, Adrian Hawryluk <adrian.hawryluk-at-
gmail....@nospam.comwrote:
Quote:
nikl...@microsoft.com wrote:
Quote:
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:
>
Quote:
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

  #5  
Old March 22nd, 2007, 09:55 PM
James Curran
Guest
 
Posts: n/a
Default Re: inheriting the operator<<

On Mar 22, 11:54 am, "johnmmcparland" <johnmmcparl...@googlemail.com>
wrote:
Quote:
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.



  #6  
Old March 22nd, 2007, 10:15 PM
Ian Collins
Guest
 
Posts: n/a
Default Re: inheriting the operator<<

johnmmcparland wrote:
Quote:
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.
  #7  
Old March 23rd, 2007, 09:05 PM
niklasb@microsoft.com
Guest
 
Posts: n/a
Default Re: inheriting the operator<<

On Mar 22, 9:59 am, Adrian Hawryluk <adrian.hawryluk-at-
gmail....@nospam.comwrote:
Quote:
>
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. :-)

 

Bookmarks

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Popular Articles

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over 205,338 network members.