6

I would like to clearly distinguish between 3D and 2D points in my code. The obvious solution would be to have separate classes.

On the other hand conversions from 3D points with z = 0 to 2D points are quite common. Therefore I would like to use a common base class so I can do those conversions in-place in memory. To keep the types apart clearly I would like to forbid the implicit conversion to that base class. Is that doable?

Or is there maybe a different way to create different types with similar function like this?

Sarien
  • 6,362
  • 6
  • 33
  • 49
  • 3
    hm, you may want to have a look here (hint: `explicit` ) :-) http://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-in-c-mean – Najzero Mar 18 '13 at 12:38
  • Can you give an example of this "in-place in memory" conversion you are talking abour? a priori, I think any public inheritance between a 2D a 3D points seems unnatural and confusing. – juanchopanza Mar 18 '13 at 12:49
  • I don't see how a common base class is supposed to allow you to convert a 3D point to a 2D point in-place anyway. Suppose `B` is a base of both `2Dpoint` and `3Dpoint`, with the `x` and `y` coords stored in `B`. Suppose further that you have an instance of `3Dpoint` and you want an instance of `2Dpoint` without copying anything. What next? – Steve Jessop Mar 18 '13 at 12:51

4 Answers4

2

This doesn't answer your question, but to solve your problem you could make a method in the 3D class returning a 2D point when requested.

Some programmer dude
  • 380,411
  • 33
  • 383
  • 585
2

You might derive the child classes privately:

class PointBase {
  // ...
};

class Point2D : private PointBase {
  // ...
};

class Point3D : private PointBase {
  // ...
};

Side effect of this approach is that also any public members of the PointBase would be inaccessible from outside, so the subclasses would have to make them accessible explicitly, either by providing proxy methods for them, or specifying them with the keyword using. That's why I would go this way only if the common logic in PointBase is considerable and having it implemented on a single place brings more benefit then the mentioned disadvantage.

mity
  • 2,259
  • 16
  • 20
  • True, I'm just the old school so often easily forget the new C++ features. But although `using` definitely is less typing, the developer must still care about making the relevant methods from `PointBase` accessible. – mity Mar 18 '13 at 12:55
  • Edited the answer to include it. – mity Mar 18 '13 at 13:01
1

If your point is stored as a vector, you could define your 3D and 2D point classes as templated classes with int parameter which will specify dimension count:

template<int dimensions> class Point {
    vector<int> coords;
    Point() : coords(dimensions) {}
    ....
    template<int other_dimensions> convertToPoint() const
    {
        // Handle different options here like:
        //   dimensions > other_dimensions
        //   dimensions < other_dimensions
        // et cetera
    }
};

And instantiate point classes:

typedef Point<2> Point2D;
typedef Point<3> Point3D;
Point2D pt = Point3D(1, 2, 3).convertToPoint<2>(); // Point2D(1, 2);
Point3D pt = Point2D(4, 5).convertToPoint<2>(); // Point3D(4, 5, 0);

This way, you'll have the same logic but completely different types and easy conversions. Not to mention you'll have to define only one class instead of two separate ones.

umi
  • 3,402
  • 2
  • 17
  • 12
1

If you want to access the 2d part of your 3d vector without any copying, there really is only one sane solution.

class Vector2d { ... };
class Vector3d {
    Vector2d part2d;
    double z;
public:
    Vector2d& as2d() { return part2d; }
};

Any inheritance-based shenanigans are very likely to result in bad design, undefined behavior, or both.

Sebastian Redl
  • 64,900
  • 8
  • 112
  • 148
  • Depending on the functions operating on those points it may be useful to be able to access private or protected members but you are correct: If not, your solution should be prefered. – Sarien Mar 18 '13 at 17:21