【问题标题】:C++: use own class in a multiset containerC++:在多集容器中使用自己的类
【发布时间】:2013-05-06 00:46:59
【问题描述】:

起初我是新来的,英语不是我的母语,所以对任何语法错误表示歉意,但我发现这个社区真的很好,所以我会尽量准确地提出我的问题。

我想将我自己的类对象添加到一个 stl 容器 multiset 中,并想用我自己在我的类中定义的重载的 less 运算符对其进行排序。我真的尝试了几种解决方案,但都没有真正奏效,所以我希望有人能给我一些有用的提示来解决它。

这是我对类定义的总体思路:

class object {
public:
    int first;
    string second;

    object(int f, string s) {
         first = f;
         second = s;
    }

    bool operator<(const object &comp) {
        return first < comp.first;
        }
};

这是我的第一次尝试,但没有成功,所以我也尝试将重载的运算符声明为友元方法,但也没有用。

这是我的主要功能的简短代码摘录:

includes ...
//code omitted
int main() {
    multiset<object*> mmset;

    mmset.insert(new object(10, "test"));
    mmset.insert(new object(11, "test"));

    return 0;
 }

过了一会儿,我开始调试我的代码并试图找出问题所在,我遇到了以下让我有点怀疑的事情。

从 stl 中提取代码:

// TEMPLATE STRUCT less
template<class _Ty>
struct less : public binary_function<_Ty, _Ty, bool>
    {   // functor for operator<
    bool operator()(const _Ty& _Left, const _Ty& _Right) const
    {   // apply operator< to operands
          return (_Left < _Right);
    }
    };

我在这一行设置了一个断点,并观察了程序在这里做了什么,我不知道为什么,但它只比较两个对象的地址并返回所以总是假的。尽管运算符存在并且 _Left 和 _Right 变量包含我的对象的地址,但它从不调用我重载的 less 运算符。

如果有人可以帮助我,我将不胜感激。

最好的问候

汤姆

【问题讨论】:

  • 关于您的第一次尝试,您所说的“它没有用”是什么意思?没有编译?运行时崩溃?没有给出预期的结果?错误信息是什么?
  • 是的,当然这有点含糊。我的意思是它没有给出预期的结果。程序本身运行没有任何错误,只是它没有排序。

标签: c++ stl operator-overloading containers multiset


【解决方案1】:

您没有将objects 存储在您的multiset 中。您正在存储object*s。这些是指向objects 的指针。这意味着该集合将对您插入其中的指针进行排序。

看来你真的只是想要一个multiset&lt;object&gt;

multiset<object> mmset;
mmset.emplace(10, "test");
mmset.emplace(11, "test");

现在它将使用&lt; 来比较objects 本身。

如果您真的想存储指针,则需要为multiset 提供一个自定义比较器。在 C++11 中,您可以使用 lambda 轻松做到这一点:

auto f = [](int* a, int* b) { return *a < *b; };
std::multiset<int*, decltype(f)> mmset(f);

在 C++11 之前,您可以创建一个实现 operator() 的函数对象,其主体与此 lambda 函数相同。

【讨论】:

  • 他可能也需要自己的operator&lt; const
  • 感谢您的快速回答!!是的,我已经担心过这样的事情......但是必须有一个解决方案来解决这个问题,而无需将整个对象直接插入集合中。将完整的对象复制到集合中效率不高。特别是如果对象的大小增长。它只是一个原型,我很快就会为我的对象添加更多数据类型。
  • @user2372782 如果你真的想包含指针,我会添加解决方案。注意编辑。
【解决方案2】:

感谢您的帮助。这似乎是解决这个问题的好方法。

我在新的 C++11 标准中进行了更深入的搜索,发现还有另一种可能的解决方案可以通过更简单的实现来解决这个问题,但结果相同 :) 我会将其发布为其他有相同问题的寻求者的信息。

您可以向任何构造函数传递一个 stl 容器一个所谓的比较对象,该容器将使用该对象来排列您的内容。 您唯一需要做的就是在您的类中定义重载的operator() 并将它们“误用”为比较运算符。

class object {
    int first;
    string second;

    object() { };
    object(int f, string s) {
       first = f;
       second = s;
    }

    bool operator()(const object *comp1, const object *comp2) const {
       return comp1->first < comp2->first;
    }
}

您现在还要做的另一件事是将object 作为容器定义中的第二个参数传递:

multiset(object*, object) mmset;

您也可以为此目的使用一个额外的类来进行比较,否则您需要一个默认构造函数才能以这种方式使用此类。

【讨论】:

    猜你喜欢
    • 2011-01-31
    • 2012-03-13
    • 2011-02-20
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    相关资源
    最近更新 更多