你是否封装了标量?

时间:2009-02-09 09:25:43

标签: strong-typing granularity

我发现自己定义了类:

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

与将普通双打角度化存储相比,它具有许多优点。

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

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 ......

2 个答案:

答案 0 :(得分:4)

只要有意义,我就会这样做。与How do you make wrong code look wrong? What patterns do you use to avoid semantic errors?比较。

在Joel的文章的例子中,他讨论了两个案例:

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

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

解决您的缺点:

  

缺点1,冗长且意外的语法

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

  

缺点2,每一件事都有太多的课程,你在哪里划线?

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

当然,总是需要权衡利弊。但是,我相信只要任何一个优势适用于你,这个缺点就是平衡。

答案 1 :(得分:1)

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