这过于聪明还是不安全?

时间:2010-05-16 20:35:51

标签: c++ operator-overloading

我最近正在编写一些代码并决定在c ++中运行我的运算符重载,因为我以前从未真正实现它。所以我使用比较函数重载了我的矩阵类的比较运算符,如果LHS小于RHS则返回0,如果LHS大于RHS则返回1,如果它们相等则返回2。然后我在整数上利用了c ++中的逻辑非属性,以便在一行中得到我的所有比较:

inline bool Matrix::operator<(Matrix &RHS){
  return ! (compare(*this,RHS));
}
inline bool Matrix::operator>(Matrix &RHS){
  return ! (compare((*this),RHS)-1);
}
inline bool Matrix::operator>=(Matrix &RHS){
  return compare((*this),RHS);
}
inline bool Matrix::operator<=(Matrix &RHS){
  return compare((*this),RHS)-1;
}
inline bool Matrix::operator!=(Matrix &RHS){
  return compare((*this),RHS)-2;
}
inline bool Matrix::operator==(Matrix &RHS){
  return !(compare((*this),RHS)-2);
}

显然我应该将RHS作为const传递,我可能不会再次使用这个矩阵类而且我不想编写另一个不是仅仅为了获取数组索引值的引用的函数比较器操作。

根据建议,这里是代码,如果Compare返回-1表示less,0表示相等,1表示正数。

inline bool Matrix::operator<(Matrix &RHS){
  return ! (compare(*this,RHS)+1);
}
inline bool Matrix::operator>(Matrix &RHS){
  return ! (compare((*this),RHS)-1);
}
inline bool Matrix::operator>=(Matrix &RHS){
  return compare((*this),RHS)+1;
}
inline bool Matrix::operator<=(Matrix &RHS){
  return compare((*this),RHS)-1;
}
inline bool Matrix::operator!=(Matrix &RHS){
  return compare((*this),RHS);
}
inline bool Matrix::operator==(Matrix &RHS){
  return !(compare((*this),RHS));
}

我不知道这确实增加了可读性。

8 个答案:

答案 0 :(得分:22)

是的,它过于聪明 - 我读了那段代码,并且必须考虑为什么你从名为compare的函数中减去两个。不要让我思考。

如果你聪明地让你的代码适合一行,那么你就会遇到困难的优先事项。您应该根据需要使用尽可能多的行来使代码尽可能清晰。

  

必须编写程序供人们阅读,并且只有机器才能执行。 (Abelson&amp; Sussman,计算机程序的结构和解释)

答案 1 :(得分:8)

是的,这太复杂了。

compare应返回0表示相等的值,如果this更大则为正数,如果this更小则为负数。

它会更简单,甚至可以表现。

如果我将此代码用于审核,我会将其标记为应该修复的内容。

答案 2 :(得分:8)

据我所知,这是安全的,但每次阅读代码的人都会看两次。你为什么想做这个?

无论如何,为了进行比较,你需要的只是<==!=,其余的都是规范的,我主要是通过肌肉记忆来写。另外,二元运算符平等地处理它们的操作数(它们不管它们)应该IMO实现为非成员。鉴于此,加上使用理智的比较函数(-10+1)并添加必要的const,我来到这里:

// doing real work
inline bool operator<(const Matrix& l, const Matrix &r)
{
  return -1 == compare(l,r);
}
inline bool operator==(const Matrix& l, const Matrix &r)
{
  return 0 == compare(l,r);
}
// canonical
inline bool operator> (const Matrix& l, const Matrix &r) {return r < l;}
inline bool operator>=(const Matrix& l, const Matrix &r) {return !(l < r);}
inline bool operator<=(const Matrix& l, const Matrix &r) {return !(r < l);}
inline bool operator!=(const Matrix& l, const Matrix &r) {return !(l == r);}

比较可能不如你的聪明,但所有见过strcmp()的人都会立即知道他们做了什么。请注意,我甚至为编译器添加了0 != compare(...),这完全没有必要。对于人类IMO来说,它更明确地发生了什么,而不是对bool的隐式演员。此外,它强调了operator<实现的对称性。

答案 3 :(得分:5)

使用六个比较运算符中的任何一个将compare的输出与0进行比较,将为相应的重载运算符生成正确的结果。这样你的代码就会非常易读,而且很明显它是正确的(如果compare正确实现的话)。

inline bool Matrix::operator < (const Matrix &RHS){
  return compare(*this, RHS) < 0;
}
inline bool Matrix::operator > (const Matrix &RHS){
  return compare(*this, RHS) > 0;
}
inline bool Matrix::operator >= (const Matrix &RHS){
  return compare(*this, RHS) >= 0;
}
inline bool Matrix::operator <= (const Matrix &RHS){
  return compare(*this, RHS) <= 0;
}
inline bool Matrix::operator != (const Matrix &RHS){
  return compare(*this, RHS) != 0;
}
inline bool Matrix::operator == (const Matrix &RHS){
  return compare(*this, RHS) == 0;
}

答案 4 :(得分:3)

如果你担心某些事情是否过于聪明......可能是: - )

答案 5 :(得分:2)

聪明?

警告:请参阅评论

我认为!=调用compare(检查两个矩阵的所有值以找出哪个更大)是不合理的,因为如果m1[0][0]!=m2[0][0]那么{{1} }}已经可以返回!=。因此,我认为简化编写这些运算符是一个不错的主意,如果性能根本不重要,那么它可以被认为是聪明的。但是如果性能确实很重要,那就不聪明了。

安全?

我也认为这是安全的,因为它会产生正确的结果。

答案 6 :(得分:2)

如前所述,我认为标准方式是返回&lt;当LHS <0时, RHS,&gt; 0表示LHS&gt; RHS,0表示平等。

但我可以问另一个问题吗?为什么要在这里使用运算符重载?运算符重载背后的想法是(或应该)能够以直观的方式使用对象。但据我所知,除了(in)相等之外,没有比较矩阵的标准定义。至少我不知道。那么当我读到M1&lt;时,我会怎么想呢? M2?

让我猜一下:运算符&lt;()和运算符&gt;()只是为了完整而添加,但实际上永远不会在现实代码中使用 - 对吧?如果是这样,请不要实施它们。

答案 7 :(得分:1)

我会按照自己的方式给你:

#include <boost/operators.hpp>

class Matrix: boost::equality_comparable<Matrix
            , boost::less_than_comparable<Matrix
              > >
{
}; // class Matrix

bool operator==(const Matrix&, const Matrix&);

bool operator<(const Matrix&, const Matrix&);

我使用的线条少于没有任何聪明技巧的线条。至于Boost?嗯,它现在非常标准,并且在线记录。您可以随时添加一些评论:

// boost::equality_comparable: automatically generate != from ==
// boost::less_than_comparable: automatically generate >, <=, >= from <
// search for Boost.Operators on the web to get more information

最后一句话:我不知道你正在编写的特定应用程序,但是使用矩阵我总是发现有一个Matrix基类和一些TMatrix子类(模板)是一个好主意,如T所示,在编译时已知维度。然后,您可以在TMatrix上提供只能处理类似维度的矩阵的运算符,因为其他任何东西都是异端,因此具有编译时诊断。