2

我发现自己定义了如下类:

struct AngleSize {
    explicit AngleSize(double radians) : size(radians) {}
    double size;
};

与将角度尺寸存储为普通双精度数相比,这具有许多优势。

优点 1,它可以定义这 2 个不同的构造函数:

Vec2::Vec2(double x, double y);
Vec2::Vec2(double length, AngleSize direction);

...后一个明确称为Vec2(1, AngleSize(5));
(尽管在这种情况下,静态工厂函数Vec2::fromPolar(1, 5)可能同样好?)

优点 2,它更类型安全,捕获以下错误:

double temperature = air.getTemperature();
Vec2 v(someLength, temperature);

然而一切都不是很好。

缺点1、冗长且出人意料的语法

Vec2::Vec2(double length, AngleSize direction) {
    x = length * cos(direction.size);
    y = length * sin(direction.size);
}

呃,这真的应该说cos(direction)在不允许不安全的隐式转换的情况下,我需要详细地访问实际值。

缺点2每件事的课程太多,你在哪里画线?

struct Direction { // angle between line and horizontal axis
    explicit Direction(AngleSize angleSize);
    AngleSize angleSize;
};

struct Angle { // defined by "starting and ending angle" unlike AngleSize
    Angle(Direction startingDir, Direction endingDir);
    Angle(Direction startingDir, AngleSize size);
    Angle(Line line1, Line line2);
};

struct PositionedAngle {
    // angle defined by two rays. this is getting just silly
    PositionedAngle(Ray firstRay, AngleSize angle);
    PositionedAngle(Point center, AngleSize fromAngle, AngleSize toAngle);
    // and so on, and so forth.
};
// each of those being a legit math concept with
// distinct operations possible on it.

在这种情况下,你自己会怎么做?

另外,我在哪里可以阅读有关此问题的信息?我想boost可能有什么相关的?

请注意,这不仅仅是几何,它适用于任何地方。想想posix socklen_t ...

4

2 回答 2

4

只要有意义,我就会这样做。与如何使错误的代码看起来不正确?您使用什么模式来避免语义错误?.

在 Joel 的文章示例中,他讨论了两种情况:

  • 需要在输出前清理字符串的 Web 应用程序的情况。他提出类型前缀来区分类型。但是,我认为简单地定义两种不同的字符串类型要好得多。最简单的方法就是引入一个SafeString类型。只有这种类型可以直接发送给客户端。必须转换正常的字符串类型(显式或隐式转换;在这种情况下无关紧要,因为隐式转换仍然可以清理字符串)。

  • 程序员需要区分屏幕坐标和文档坐标的 Microsoft Word 示例。这是两个不同类型提供很多优势的经典案例,即使这些类型几乎相同(它们都描述了 2D 点)。

为了解决你的缺点:

缺点1、冗长且出人意料的语法

大多数语言实际上允许以使类使用预期语法的方式重载函数/运算符。在 C++ 中,这甚至是最佳实践:“让你自己的类型表现得像ints”。通常,这不需要在存在适当重载的情况下进行隐式强制转换。

缺点2,每件事的课程太多,你在哪里画线?

根据需要制作尽可能多的自定义类型(但不是更多)。一些语言,例如 Haskell,实际上鼓励类型的扩散。唯一让我们对像 C++ 这样的语言犹豫不决的是懒惰,因为我们必须编写大量样板代码。C++0x 通过引入类型安全的类型别名使这变得稍微容易一些。

当然,总是需要权衡取舍。但是,我相信只要有任何一个优势适用于您,这个劣势就可以简单地平衡。

于 2009-02-09T09:41:38.210 回答
1

我不这样做,因为它带来的微小优势,我会发现它过于冗长和复杂。我有时会做一个简单typedef的事情来使事情更容易阅读,但仅此而已。

于 2009-02-09T09:34:22.597 回答