6

我想在我的代码中清楚地区分 3D 和 2D 点。显而易见的解决方案是有单独的类。

另一方面,从 z = 0 的 3D 点到 2D 点的转换非常普遍。因此我想使用一个通用的基类,这样我就可以在内存中就地进行这些转换。为了清楚地将类型分开,我想禁止隐式转换为该基类。那可行吗?

或者是否有不同的方法来创建具有类似功能的不同类型?

4

4 回答 4

2

这不能回答您的问题,但要解决您的问题,您可以在 3D 类中创建一个方法,在请求时返回 2D 点。

于 2013-03-18T12:38:04.340 回答
2

您可能会私下派生子类:

class PointBase {
  // ...
};

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

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

这种方法的副作用是,任何公共成员PointBase也无法从外部访问,因此子类必须通过为它们提供代理方法或使用关键字指定它们来显式访问它们using。这就是为什么只有当通用逻辑PointBase相当大并且在一个地方实现它比提到的缺点带来更多好处时,我才会这样做。

于 2013-03-18T12:43:34.330 回答
1

如果您的点存储为矢量,您可以将 3D 和 2D 点类定义为模板类,并带有int指定维度计数的参数:

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
    }
};

并实例化点类:

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);

这样,您将拥有相同的逻辑但完全不同的类型和简单的转换。更不用说你只需要定义一个类而不是两个单独的类。

于 2013-03-18T13:03:51.023 回答
1

如果您想在不进行任何复制的情况下访问 3d 矢量的 2d 部分,那么实际上只有一个合理的解决方案。

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

任何基于继承的恶作剧都很可能导致糟糕的设计、未定义的行为或两者兼而有之。

于 2013-03-18T15:33:09.667 回答