jcoffin@taeus.com (Jerry Coffin) wrote in message
[...]
[color=blue]
> IMO, it's perfectly reasonable for a class to overload the insertion
> and/or extraction operators to do I/O on complete objects. One common
> (and useful) idiom for that is to have a virtual member function to do
> the I/O, and have it invoked from a global overload of operator<< or
> operator>>, as applicable. In that case, a member function doing I/O
> makes perfect sense.[/color]
I believe I'm following you here so if I were to re-write the above
statement in terms of source code:
class X
{
int Jdx;
friend std::ostream& operator << (std::ostream& os, X const& x);
public:
virtual void std::ostream& Print ( ostream& os ) { os << Jdx; }
}
friend std::ostream& operator << (std::ostream& os, X const& x)
{
return x.Print(os);
}
So far so good?
Now heres where this approach gets interesting from the perspective of
an apprentice. For the purposes of discussion, assume class X has 10
member data, three of which is - say - line of sight positions with
units direction cosines.
Occassionally I'm interested in outputting all 10 member data.
Similarily, there are times when I'm interested in outputting only the
line of sight positions.
Perhaps irrelevant, but lets also assume the environment allows one
the opportunity to type in the name of a function and pass parameters
to function calls. Upon doing that the function executes. In any
event, how do you approach the print function?
[color=blue]
>
> OTOH, if your member function's basic idea is to produce a value
> (which you happen to be printing out at the moment) then having it do
> the I/O as well probably isn't such a great idea.
>
> There are a couple more possibilities. One is to put the computation
> (or whatever) into a base class that also has a (possibly pure)
> virtual function that handles processing the output. Then a derived
> class can specify how the output will be processed by overloading that
> virtual function.[/color]
For instance?
[color=blue]
> A similar possibility is to pass a parameter that specifies how to
> process the output -- one way is to pass a pointer to a function to be
> invoked on the output (this more or less matches the version above
> with virtual functions). Another is to use an iterator, and write the
> output to the iterator. In this case, you can easily put the output
> into something like a collection, or you can pass a
> std::ostream_iterator, which will write the data to a stream.[/color]
This sounds like
vector<int> Vec(5);
copy (Vec.begin(), Vec.end(), ostream_iterator<int>(cout, ' '));
Yes/No?
Now how would you map said approach to a class X?
[color=blue]
> Choosing between these isn't necessarily easy.[/color]
Agreed. There are times when one's faced with multiple classes and a
need to instrument data. Your first option is straightforward in the
sense that each class could maintain their own print function. A
while back I overheard a professor discussing the creation of an
'instrumentation' class which supports the concept of plug-in. In
essence, you'd plug-in (assuming I understand the prof) the
instrumentation class into class X and sure enough/somehow your data
will be extracted for you. That's a novel idea and sounds suprisingly
efficient. Truth is, the idea is incomprehensible/makes no sense to
me.