473,473 Members | 2,277 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

need virtual behavior for friend operator<<()

hi.

I don't use exceptions much in the embedded world, but for my plugin
interface to a hardware MPEG encoder I'd like to, since there are so many
places that the crummy kernel driver can do bad things to my userland
program. I hope this news client doesn't reformat my example below and
make it impossible to read. :^)

consider the following exception heirarchy

// ----------------------------

struct base {
string message;
base(const char* mess): message(mess) {}
friend ostream& operator<<(ostream& s, base& r) {
s << r.message;
return s;
}
virtual const char* is_a() { return "base"; }
};

// ------------------------

struct derived: public base {
string method;
derived(const char* m, const char* f=""):
base(m), method(f) {}
const char* is_a() { return "derived"; }
friend ostream& operator<<(ostream& s, derived& r) {
s << r.message;
if (r.method.length()) s << " in " << r.method;
return s;
};
int main() {
try {
throw derived("in try block","main()");
}
catch(base& b)
{ cout << b.is_a() << " " << b << endl; };
// previous line does b.is_a() virtual correctly
// but uses friend operator<<() from base instead of
// from derived

return 0;
}
I want a generic catch block that catches the superclass of my exceptions
and correctly binds to the class that really threw the exception. I know
that I could make a virtual output() method for each derived class and
output << b.output() but is there an elegant way to do this without
adding another virtual into each derived class?

in the past I've tried overloading the redirect operators within the
classes but never had any luck. I've only ever been able to make them
work well as friend methods and I don't believe a virtual friend would
exist...Ever have a virtual friend as a kid?

I hope I'm clearly explaining, and I anticipate some interesting
comments on this one. :^)
Jan 23 '07 #1
5 2240
I was afraid of this...the blasted news client joined some lines.

I'll try to fix them below


On Mon, 22 Jan 2007 22:26:16 -0500, noone wrote:
hi.

I don't use exceptions much in the embedded world, but for my plugin
interface to a hardware MPEG encoder I'd like to, since there are so many
places that the crummy kernel driver can do bad things to my userland
program. I hope this news client doesn't reformat my example below and
make it impossible to read. :^)

consider the following exception heirarchy

// ----------------------------

struct base {
string message;
base(const char* mess): message(mess) {}
friend ostream& operator<<(ostream& s, base& r) {
s << r.message;
return s;
}
virtual const char* is_a() { return "base"; }
};

// ------------------------

struct derived: public base {
string method;
derived(const char* m, const char* f=""):
base(m), method(f) {}
const char* is_a() { return "derived"; }
friend ostream& operator<<(ostream& s, derived& r) {
s << r.message;
if (r.method.length()) s << " in " << r.method; return s;
};
int main() {
try {
throw derived("in try block","main()");
}
catch(base& b)
{ cout << b.is_a() << " " << b << endl; };
// previous line does b.is_a() virtual correctly
// but uses friend operator<<() from base instead of
// from derived

return 0;
}
}

I want a generic catch block that catches the superclass of my exceptions
and correctly binds to the class that really threw the exception. I know
that I could make a virtual output() method for each derived class and
output << b.output() but is there an elegant way to do this without
adding another virtual into each derived class?

in the past I've tried overloading the redirect operators within the
classes but never had any luck. I've only ever been able to make them
work well as friend methods and I don't believe a virtual friend would
exist...Ever have a virtual friend as a kid?

I hope I'm clearly explaining, and I anticipate some interesting comments
on this one. :^)
Jan 23 '07 #2

noone wrote:
consider the following exception heirarchy

// ----------------------------

struct base {
string message;
base(const char* mess): message(mess) {}
friend ostream& operator<<(ostream& s, base& r) {
s << r.message;
return s;
}
virtual const char* is_a() { return "base"; }
};

// ------------------------

struct derived: public base {
string method;
derived(const char* m, const char* f=""):
base(m), method(f) {}
const char* is_a() { return "derived"; }
friend ostream& operator<<(ostream& s, derived& r) {
s << r.message;
if (r.method.length()) s << " in " << r.method;
return s;
};
int main() {
try {
throw derived("in try block","main()");
}
catch(base& b)
{ cout << b.is_a() << " " << b << endl; };
// previous line does b.is_a() virtual correctly
// but uses friend operator<<() from base instead of
// from derived

return 0;
}
I want a generic catch block that catches the superclass of my exceptions
and correctly binds to the class that really threw the exception. I know
that I could make a virtual output() method for each derived class and
output << b.output() but is there an elegant way to do this without
adding another virtual into each derived class?

in the past I've tried overloading the redirect operators within the
classes but never had any luck. I've only ever been able to make them
work well as friend methods and I don't believe a virtual friend would
exist...Ever have a virtual friend as a kid?
Here's how I've solved this in the past:

1) Create a virtual method 'output,' as you suggested
virtual ostream& output(ostream& s) const;

I forget whether I had to make it public, or could make it protected.

2) Implement it for each of the classes.

3) For your base class (only), implement the << operator, in terms of
output:
friend ostream& operator<<(ostream& s, const base& b) {
return b.output(s);
};

Then any/all clients of the class can just do something like:
cout << my_instance;

It seems a little yucky, but the yuckiness is localized to your
exception hierarchy, the code that uses it is clean.

Michael

Jan 23 '07 #3
On Mon, 22 Jan 2007 20:54:05 -0800, Michael wrote:
Here's how I've solved this in the past:

1) Create a virtual method 'output,' as you suggested virtual ostream&
output(ostream& s) const;
Yes. I was hoping to avoid this but you are confirming my suspicions
>
I forget whether I had to make it public, or could make it protected.
I'm a bad boy. I generally make things public unless an overwhelming
reason not to. :^)

It seems a little yucky, but the yuckiness is localized to your exception
hierarchy, the code that uses it is clean.
Yeah...yucky, but if it works and is maintainable then it's OK by me. I
just had to see if someone could think of something more elegant before I
go that route in the morning.

thanks

Jan 23 '07 #4
noone wrote:
On Mon, 22 Jan 2007 20:54:05 -0800, Michael wrote:
Here's how I've solved this in the past:

1) Create a virtual method 'output,' as you suggested virtual ostream&
output(ostream& s) const;

Yes. I was hoping to avoid this but you are confirming my suspicions
It seems a little yucky, but the yuckiness is localized to your exception
hierarchy, the code that uses it is clean.

Yeah...yucky, but if it works and is maintainable then it's OK by me. I
just had to see if someone could think of something more elegant before I
go that route in the morning.
The best way to deal with an over-engineered solution is not to look
for ways to under-engineer its integration into the program.
Instead, I would recommend adopting a solution more in line with the
scope of the problem that needs to be solved.

Specifically - and I feel that I must square with you - there is no
such thing as an "exception hierarchy." There is no literature that
describes "exception hierarchies", there are no experts who study them
for a living, no journals dedicated to their research - in short,
nothing.

Nor is there much value in thinking about exceptions as a "hierarchy"
in the first place. In fact, few mental models could be any less
accurate. In reality exceptions are nearly all identical - only the
particulars of error itself vary. Therefore I think it would be more
productive (and a lot less work) to replace the elaborate exception
class hiearchy with a single exception type. And have this type simply
store the exception's useful information - which could include:

1. an exception id to uniquely identify the error (int)
2. description as a string (for diagnostic messages)
3. point at which exception was thrown (filename, line number)
4. other exception-specific information

After all, the goal of this work should be for the program make the
best use out of C++ expections. The goal should not be how to take an
elaborate class hiearachy that happens to be lying around, stick it
into a program so that a) it will do something useful and b) won't
require a lot of work to get to point a).

Or to put it another way: the focus should never be on finishing the
solution - the focus should always be on eliminating the problem.

Greg

Jan 23 '07 #5
On Mon, 22 Jan 2007 23:09:56 -0800, Greg wrote:
Specifically - and I feel that I must square with you - there is no such
thing as an "exception hierarchy." There is no literature that describes
"exception hierarchies", there are no experts who study them for a living,
no journals dedicated to their research - in short, nothing.
Nor is there much value in thinking about exceptions as a "hierarchy" in
the first place. In fact, few mental models could be any less accurate. In
reality exceptions are nearly all identical - only the particulars of
error itself vary. Therefore I think it would be more productive (and a
lot less work) to replace the elaborate exception class hiearchy with a
single exception type. And have this type simply store the exception's
useful information - which could include:

1. an exception id to uniquely identify the error (int) 2.
description as a string (for diagnostic messages) 3. point at which
exception was thrown (filename, line number) 4. other
exception-specific information

After all, the goal of this work should be for the program make the best
use out of C++ expections. The goal should not be how to take an elaborate
class hiearachy that happens to be lying around, stick it into a program
so that a) it will do something useful and b) won't require a lot of work
to get to point a).

Greg.

I suggest getting a copy of "The C++ Programming Language" by the
creator of the language Bjarne Stroustrup and reading the section on
exceptions thoroughly before writing such things, especially given the
authoritative tone that seems to come across in what is written above.

The original post was to address the capabilities of virtuals vs friends.
Exceptions just happened to be the real-world example case I chose to
display the current and preferred behavior.

Happy hacking!
Rob

Jan 26 '07 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Gianni Mariani | last post by:
Can anyone enligten me why I get the "ambiguous overload" error from the code below: friendop.cpp: In function `int main()': friendop.cpp:36: ambiguous overload for `std::basic_ostream<char,...
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...
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> ...
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;...
4
by: Rock | last post by:
I'm in the process of writing this program for complex numbers and I use DevC++. My professor on the other hand compiles on Borland 5.5. So I ocasionally save and run my work on Borland to see if...
3
by: subramanian100in | last post by:
Consider the code: #include <iostream> using namespace std; int main( ) { cout << "test string "; cout.operator<<(10).operator<<(endl);
2
by: Joe Hesse | last post by:
Hi, I have a template class and I want to define an operator << as a friend function. For each instantiation of the class I want a corresponding instantiation of operator <<. The following...
3
by: Martin T. | last post by:
Hello. I tried to overload the operator<< for implicit printing of wchar_t string on a char stream. Normally using it on a ostream will succeed as std::operator<<<std::char_traits<char> will...
6
by: Rob McDonald | last post by:
I would like to force all the classes in my hierarchy to implement the << operator for testing purposes. My base class is a pure virtual class. I started out by working with operator...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
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...
1
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...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

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.