Connecting Tech Pros Worldwide Help | Site Map

inheriting the operator<<

johnmmcparland
Guest
 
Posts: n/a
#1: Mar 22 '07
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

niklasb@microsoft.com
Guest
 
Posts: n/a
#2: Mar 22 '07

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

Adrian Hawryluk
Guest
 
Posts: n/a
#3: Mar 22 '07

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/]______\/
johnmmcparland
Guest
 
Posts: n/a
#4: Mar 22 '07

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

James Curran
Guest
 
Posts: n/a
#5: Mar 22 '07

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.



Ian Collins
Guest
 
Posts: n/a
#6: Mar 22 '07

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.
niklasb@microsoft.com
Guest
 
Posts: n/a
#7: Mar 23 '07

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. :-)

Closed Thread


Similar C / C++ bytes