472,958 Members | 2,289 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

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 2209
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
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
2
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

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.