views:

510

answers:

7

Right now I am using std::pair to represent a 2d point in c++. However, I am getting annoyed with having to write

typedef std::pair<double, double> Point;

Point difference = Point(p2.first - p1.first,
                         p2.second - p1.second);

instead of being able to overload operator+ and operator-.

So, my question is, to make my Point class, should I

  • Publicly derive from std::pair and add my own member functions? This is nice because all my code can stay the same. I am not going to be doing anything like std::pair<double, double>* p = new Point; so I don't have to worry about things like virtual destructors.
  • Roll my own Point class, which is annoying since I am duplicating std::pair's functionality, however I am "doing it the pure way".
  • Make template specializations of operator+ and operator- for std::pair, which admittedly I don't remember if they go in source or header files.

I guess it's up for debate, I'd really like to do #1 but I don't know if it's a bad idea since I've heard that inheriting from STL is a no-no.

+10  A: 

You could roll your own Point class, but use std::pair internally to store the data. This prevents the inheritance from STL issue, but still uses std::pair's functionality.

Soo Wei Tan
+1. If you happen to read Code Complete, it suggests this exact practice: If [the class Point] *is* a [std::pair], then inherit. Otherwise, the [std::pair] should be stored as a private member, and [Point] should instead define its own interface. "point.first" doesn't make sense; point.x does.
ojrac
That's probably where I got the idea from. That book rocks!
Soo Wei Tan
+1  A: 

One other option might be to make you own Point class, and have your class "own" a std::pair that represents the point coordinates.

A lot of times a "HAS A" (composition) relationship is preferable over an "IS A" (inheritance) relationship.

Andy White
+1  A: 

I think "Best Practices" would say to roll your own Point class. This way, you can make it 3D much easier down the road.

Tom Ritter
there is absolutely no need for 3d. It's for a game. A 2d game.
rlbond
2 dimensions should be enough for anybody!!! Sorry about that
1800 INFORMATION
+1  A: 

Private inheritance aka inheritance of implementation, is your friend.

This follows logically: a Point is NOT a std::pair, you don't want to have a public up-cast conversion from Point to std::pair, but you do want to use std::pair's internals.

The other possibility is to a has-a relationship, or composition: each Point has-a privbate std::pair it uses internally.

In point of fact, there's not much difference between composition and private inheritance, except that in the latter you can force an up-cast to std::pair in a Point member function.

tpdi
A: 

Roll your own Point class. This will allow you to do any number of things with it in the future. Specifically, I have solved this sort of problem before, and what I have found to be useful is to define my own Point structure, and create a Point class which inherits from it.

Full disclosure: I do not like the STL very much.

McWafflestix
+1  A: 

Better than rolling your own: grab an existing free Vector/Point library. One recommendation: the one attached to Essential Math for Games Programmers. You can use whatever library you find as a starting point, then optimize / specialize / tweak from there.

leander
+1  A: 

I'd be in favour of creating your own Point class and use either private inheritance or composition if you want to employ std::pair's functionality. The problem with the typedef (as I am sure you are aware) is that any function you write that takes a Point will also be usable by anything represented as a std::pair<double, double>, which may not be valid.

With this in mind, another option exists of just creating some free builder functions like

Point addPoints(const Point& p1, const Point& p2);
Point diffPoints(const Point& p1, const Point& p2);

(the function names could be better).

Anthony Cramp