在C ++中重载比较运算符导致“无效的运算符<”

时间:2011-04-26 05:25:43

标签: c++ sorting operators operator-overloading overloading

目前正在尝试使用C ++

对对象的矢量进行排序,每个对象包含一个字符串

字符串可以包含字母或数字(由于设计约束,这是必要的,因为比较器可以更改)。

目前,对象的类被重载,因此当比较两个对象时,将比较它们包含的字符串。这是有用的 - 然而,当我使用排序操作(例如STL排序)按顺序放置对象时,它将按顺序排序三个字符串,如“1”,“4”,“12” “1”,“12”,“4”。 4大于12,但因为它从最左边的数字开始比较,所以发生这种'不正确'排序。

我最初的反应是改变比较操作的重载方式。我首先检查我正在比较的字符串的长度 - 如果字符串的内容大于或小,这将是一个明显的标志。

// overloaded comparision operators
friend bool operator<(const nodeRecord & record1, const nodeRecord & record2){
    // we need to deal with strings of different lengths...
    if(record1.comparator.length() < record2.comparator.length())
        return true;
    else
        return (record1.comparator < record2.comparator);
}

此操作导致“表达式:无效运算符&lt;”运行期间的消息。

关于我犯错的地方的任何想法?似乎我应该能够准确地指示操作如何进行排序操作 - 即使它是无效的,因为我当前正在使用向量来包含对象。

nodeRecord对象初始化期间的比较器:

nodeRecord(int fromNode, int toNode, int connectionCost, bool compareByCost = false){
    // take the provided stock information and insert it into the object
    stringstream fromNodeSS;
    fromNodeSS << fromNode;
    this->fromNode = fromNodeSS.str();
    stringstream toNodeSS;
    toNodeSS << toNode;
    this->toNode = toNodeSS.str();
    this->connectionCost = connectionCost;

    // set the comparator to our chosen comparision term
    if (!compareByCost){
        this->comparator = this->fromNode; // we use from node in this case, since we build the tree outwards
    }
    else{
        stringstream ss;
        ss << this->connectionCost;
        this->comparator = ss.str(); // we use the connection cost in this case, to allow us to sort new connections
    }

    // set this as a non-null (active) record
    this->nullRecord = false;
}

3 个答案:

答案 0 :(得分:10)

您的操作符实际上无效。

如果您希望运算符<可用于排序,则它必须具有许多数学属性。一个是AntiSymmetry属性:

  

x < y => !(y < x)

让我们定义x = "b"y = "aa"

  • x < y因为"b"的长度低于"aa"的长度
  • y < x因为"aa"不如"b"

哼哼?

另请注意,如果数字以0为前缀,您的定义很奇怪。

哦,比较字符串比比较字符慢。

我的看法?停止使用比较信息更改节点。实际的比较模式与节点本身无关。

然后你会写两个比较方法,一个按成本比较,另一个按原点进行比较。


回到最初的问题,如何编写一个考虑["a", "b", "aa"]排序的比较器?

你几乎就在那里,但“长度”比较是不完整的。只有在长度不同的情况下,你才需要回到实际的词法比较,因此你忘记了右手边参数长度不如左手边的情况。

因此,正确的形式是,假设有两个字符串:

bool compare(std::string const& lhs, std::string const& rhs) {
  if (lhs.length() < rhs.length()) { return true; }
  if (rhs.length() < lhs.length()) { return false; } // don't forget this
  return lhs < rhs;
}

答案 1 :(得分:1)

找到以下抛出错误的代码段,然后考虑我的重载操作是如何工作的。

template<class _Ty1, class _Ty2> inline
    bool _Debug_lt(_Ty1& _Left, _Ty2& _Right,
        _Dbfile_t _File, _Dbline_t _Line)
    {   // test if _Left < _Right and operator< is strict weak ordering
    if (!(_Left < _Right))
        return (false);
    else if (_Right < _Left)
        _DEBUG_ERROR2("invalid operator<", _File, _Line);
    return (true);
    }

工作解决方案是这个(由于Matthieu M留下的评论,再次修改。)

// overloaded comparision operators
friend bool operator<(const nodeRecord & record1, const nodeRecord & record2){
    // we need to deal with strings of different lengths...
    if(record1.comparator.length() > record2.comparator.length()
        && (record1.comparator.length() !=0 && record2.comparator.length() != 0))
        return false;
    else if(record1.comparator.length() < record2.comparator.length()
        && (record1.comparator.length() !=0 && record2.comparator.length() != 0))
        return true;
    else
        return (record1.comparator < record2.comparator);
}

感谢所有帮助过的人!

答案 2 :(得分:0)

为什么不使用单个比较器并使该功能更智能一点?让它在开头检查数字字符,如果是,请执行一对strtol()atoi()并比较结果。

否则,根据非数字要求比较字符串和字符的长度。