473,394 Members | 1,734 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

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

Mar 22 '07 #1
6 1594
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Alicia | last post by:
Hello, I am trying to figure out how to call an overloaded operator<< inherited from a base class. #ifndef PHONECALL #define PHONECALL #include "time.h" #include "interval.h"
3
by: Alex Vinokur | last post by:
Member operators operator>>() and operator<<() in a program below work fine, but look strange. Is it possible to define member operators operator>>() and operator<<() that work fine and look...
3
by: Sensei | last post by:
Hi. I have a problem with a C++ code I can't resolve, or better, I can't see what the problem should be! Here's an excerpt of the incriminated code: === bspalgo.cpp // THAT'S THE BAD...
14
by: lutorm | last post by:
Hi everyone, I'm trying to use istream_iterators to read a file consisting of pairs of numbers. To do this, I wrote the following: #include <fstream> #include <vector> #include <iterator> ...
4
by: bluekite2000 | last post by:
Here A is an instantiation of class Matrix. This means whenever user writes Matrix<float> A=rand<float>(3,2);//create a float matrix of size 3x2 //and fills it up w/ random value cout<<A; the...
3
by: Carlo Capelli | last post by:
I found a change in the following code, that behaved correctly in VC++ 6. #include <strstream> using namespace std; void main() { char x; ostrstream(x, 100) << "pippo" << "pluto" << ends;...
2
by: Harry | last post by:
Hi all, I am writing a logger program which can take any datatype. namespace recordLog { enum Debug_Level {low, midium, high}; class L { std::ofstream os; Debug_Level cdl; const...
4
by: Amadeus W. M. | last post by:
What is the difference between friend ostream & operator<<(ostream & OUT, const Foo & f){ // output f return OUT; } and template <class X>
7
by: Eric Lilja | last post by:
>From a book, I know the following is true for the comparison operators: An overloaded operator that is a class member is only considered when the operator is used with a *left* operand that is an...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.