比较不同类型的对象是否被认为是好的设计?

时间:2013-07-02 20:59:26

标签: c++ operator-overloading

你会考虑这个糟糕设计的证据吗?

//FooType and BarType not in the same hierarchy
bool operator==(const FooType &, const BarType &);
bool operator<(const FooType &, const BarType &);

例如,如果FooTypedouble测量自纪元以来的秒数而BarType是三个整数(年,月和日)的元组,提供UTC日期,则比较如上“有意义”。

你见过这种类型间的比较吗?他们在C ++社区中不受欢迎吗?

4 个答案:

答案 0 :(得分:4)

首先,使用自由函数而不是成员函数没有任何问题,事实上它是推荐的做法。见Scott Meyer的How Non-Member Functions Improve Encapsulation。您可能希望在两个方向上提供比较:

bool operator==(const FooType &, const BarType &);
bool operator==(const BarType &, const FooType &);

其次,如果比较有意义,提供这些比较是完全可以接受的。例如,标准库允许您将std::complex值与浮点值进行比较,但不要小于。{/ p>

你要避免的一件事是比较没有意义。在您的示例中,其中一个时间值是double,这意味着一旦您考虑标准促销,任何浮点或整数值都会进行比较。这可能比您预期的要多,因为无法确定任何特定值是否代表时间。丢失类型检查意味着可能存在意外错误。

答案 1 :(得分:3)

个人愿景和经验

我个人并不鄙视不同类型之间的比较。我甚至鼓励它,因为它可以提高代码的可读性;做你正在做的事情似乎更合乎逻辑。在基本数字类型之外,也许是一个字符串和一个字符,我发现很难给你一个逻辑的类型内比较,我不记得见过很多。我遇到了很多像这样使用的算术运算符。

如何使用

你应该小心你正在做的事情,因为某种原因它们几乎没有被使用。如果您提供用于比较两种不同类型的函数,则结果应该是逻辑的以及用户直观期望的结果。为它编写好的文档也是可取的。 Mark Ransom已经说过了,但如果用户可以在两个方向进行比较,那就很好了。如果您认为您的比较对于操作员来说不够清楚,您应该考虑使用命名函数。如果您的操作员可以有多种含义,这也是一个非常好的解决方案。

可能出现什么问题

您无法完全控制用户对您所写内容的处理方式。 tletnes给出了一个很好的例子,比较了两个整数,但结果没有意义。与此相反,两种不同类型的比较可能是非常正确的。可以很好地比较表示秒的浮点数和整数。

算术运算符

在逻辑旁边,我想展示一个带算术运算符的内部类型示例。在讨论类型内使用时,算术运算符非常类似于逻辑运算符。

假设您有一个运算符+用于二维向量和一个正方形。这是做什么的?用户可能认为它缩放了正方形,但另一个用户确信它会翻译!这些问题对您的用户来说非常令人沮丧。您可以通过提供良好的文档来解决这个问题,但我个人更喜欢的是具体命名的函数,如Translate。

<强>结论

内部类型逻辑运算符可能很有用并且可以生成干净的代码,但是错误的使用会使一切变得更加复杂。

答案 2 :(得分:1)

好的设计会决定你只应该比较兼容意义的值。通常类型是意义的好线索,但不是最后一个词,实际上在很多情况下,同一类型的两个值可能具有不相容的含义,例如以下两个整数:

int seconds = 3 //seconds
int length = 2; //square inches
if(seconds >= length){
    //what does this mean?
}

在这个例子中,我们将长度与秒进行比较,但是两者之间没有一个令人感动的关系。

int test_duration = 3 //minutes
float elapsed_time = 2.5; //seconds
if((test_duration * 60) >= elapsed_time ){
    //tes is done
}

在这个例子中,我们比较了不同类型(和单位)的两个值,但是它们的含义仍然是兼容的(它们都代表时间)所以(假设这两个存储的原因很好(例如易于使用) API等)这是一个很好的设计。

答案 3 :(得分:0)

根据Stepanov的规则(请参阅编程元素),平等与复制(构造和分配)(以及不平等)紧密相关。

因此,如果对象表示相等的值,则继续进行操作,使它们相等,但同时考虑这四个操作(相等,[复制]构造,赋值和不相等)。 通过扩展,还可以从不同类型来回转换(在另一侧进行铸造操作或构造)。

它也隐式地连接到可以应用于这些值的任何“常规”函数。 Stepanov将两个值定义为相等(如果对其应用任何(常规)函数得出相等的结果)。

我还要说的是,即使您可以比较两个相等的对象并彼此构造一个对象,但是如果可以应用于这两个对象的一组通用函数(无论是否通用)不是相关集合,或者它们的结果通常是收益如果值不相等,则比较不同类型的对象几乎没有价值。 最糟糕的是,如果其中一种类型的功能根本比另一种类型的功能更多,该怎么办?可以保持反射力吗?

最后,如果比较两个对象为 O(N ^ 2)或更高(其中 N 是对象的“大小”某种程度的对象),那么可以理解,比较对象根本没有任何价值。 (请参阅约翰·拉科斯的演讲https://www.youtube.com/watch?v=W3xI1HJUy7Q

因此,正如您所看到的,它不只是提出一个比较标准来填充[key] : value的正文,或者这是否是一个好习惯,还仅仅是个开始。 平等是如此基础,以至渗入所有程序的含义。