To overload or Not to overload

I have a class, that contains several pieces of data. I'll be using a vector of objects based on this class.

So, when it comes time to print these objects to a file (or should I wish to print one of the objects to cout) I'm trying to figgure out which way would be better.

Should I make a function in the object and pass it a refference to the fstream or cout as needed (I assume both are istreams and thus are interchangable?)

Or should I overload the << operator? (if so, how do I do this. I've never really worked with overloading before.)

What do you think?
It doesn't really matter. (You might do both.)

The difference is whether or not you think you will be using standard algorithms to manipulate your class.

Here's a little program you can play with.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

struct point
  {
  int x, y;

  point( int x = 0, int y = 0 ):
    x( x ),
    y( y )
    { }

  // Here are our class functions to read and write a point from text file
  ostream& write( ostream& outs ) const
    {
    return outs << '(' << x << ',' << y << ')';
    }

  istream& read( istream& ins )
    {
    try {
      ins >> ws; if (ins.peek() != '(') throw 0; ins.get();
      if (!(ins >> x)) throw 0;
      ins >> ws; if (ins.peek() != ',') throw 0; ins.get();
      if (!(ins >> y)) throw 0;
      ins >> ws; if (ins.peek() != ')') throw 0; ins.get();
      }
    catch (int)
      {
      if (!ins.eof())
        ins.setstate( ios::badbit );
      }
    return ins;
    }
  };

// Here are the insertion and extraction operators for point
ostream& operator << ( ostream& outs, const point& pt )
  {
  return pt.write( outs );
  }

istream& operator >> ( istream& ins, point& pt )
  {
  return pt.read( ins );
  }

int main()
  {
  vector <point> points;
  string         s;

  cout << "Please enter a list of points.\n"
          "Each point must be specified as \"(x,y)\", where x and y are integer numbers.\n"
          "Press ENTER on a blank line to finish.\n";

  // Users expect to press ENTER after inputs. However, the user may
  // enter more than one point per line. So we'll parse input one line at a time.
  while (getline( cin, s ) && !s.empty())
    {
    istringstream ss( s );
    // This is where the STL comes in. The istream_iterator uses the extraction
    // operator >> to get points from stream.
    copy(
      istream_iterator <point> ( ss ),
      istream_iterator <point> (),
      back_inserter( points )
      );
    if (ss.bad()) cout << "Remember, points must be entered as (x,y)!\n";
    }

  reverse( points.begin(), points.end() );

  // Likewise, we use the overloaded insertion operator here
  cout << "The points you entered, in reverse order:\n";
  copy(
    points.begin(),
    points.end(),
    ostream_iterator <point> ( cout, "\n" )
    );

  cout << "Bye now!\n";
  return 0;
  }

Hope this helps.
Last edited on
yea.. it does make sence.. and should work nicely.

I notice you overload the << operator outside of the class definition. I would have tried to do it inside. Thanks for the clarification.

and it gives me something else to look up and study. the copy function is new to me.
Last edited on
The insertion and extraction operators should always be defined as friend functions so as to not confuse users by requiring funky syntaxes.

Programmers expect output to look like
cout << quux;

and input to look like
cin >> quux;

Anything else violates the principle of least surprise.

(In other words, the class object should be on the right side of the iostream operator.)


I threw the copy() algorithm and stream iterators in there just to play with your brain. :-P It is a good way to learn magic.

Glad to be of help. :-)
you know what.. turns out I won't be able to print from inside the object anyway. It would require adding some headers to that module that I wanted to keep seperate from that module.

I'm going to have to do it from the main.cpp where both modules are included.

It means more work on my part, but saves file bloating.

Thanks anyway.
Topic archived. No new replies allowed.