2013-05-11 2 views
3

сначала я здесь новый, а английский - не мой родной язык, поэтому приношу свои извинения за любые грамматические ошибки, но я считаю, что это сообщество действительно приятно, поэтому я постараюсь задать свой вопрос как точную как я могу.C++: используйте собственный класс в мультимножеством контейнере

Я хочу добавить свой собственный объект класса в мультимножество контейнера stl и хочу сортировать его с помощью моего собственного перегруженного оператора меньшего размера, определенного в моем классе. Я действительно опробовал несколько решений, но ничего действительно не сработало, поэтому я надеюсь, что кто-то может дать мне полезные подсказки для его решения.

Вот моя общая идея моего определения класса:

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; 
     } 
}; 

Это была моя первая попытка, и это не сработало, так что я также попробовал объявить перегруженный оператор как метод другу, но Бесполезный» t работа также.

Вот короткий код выдержка из моей основной функции:

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

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

    return 0; 
} 

Через некоторое время я начал отладки мой код и попытаться выяснить, где проблема, и я наткнулся на следующую вещь, которые сделали я немного подозрительно.

код экстракт из СТЛ:

// 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); 
    } 
    }; 

Я поставил точку останова на этой линии и заметил, что программа делает здесь, и я не знаю почему, но он сравнивает только адреса из двух объекты и возвращать так всегда false. Он никогда не вызывает мой перегруженный меньше оператора, хотя оператор существует, а переменные _Left и _Right содержат адрес для моего объекта.

Я был бы очень признателен, если бы кто-то мог мне помочь.

Лучшие Приветствия

Том

+2

Что касается вашей первой попытки, что вы подразумеваете под "это не сработало"? Не компилировался? Сбой во время выполнения? Не дали ожидаемых результатов? Каково было сообщение об ошибке? –

+0

Да, конечно, это было немного расплывчато. Я имел в виду, что он не дает ожидаемых результатов. Сама программа работает без каких-либо ошибок, просто она не сортируется. – tom1991te

ответ

5

Вы не хранить object с в вашем multiset. Вы храните object* s. Это указатели на object с. Это означает, что набор будет заказывать указатели, которые вы вставляете в него.

Похоже, вы действительно просто хотите multiset<object>:

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

Теперь он будет использовать < сравнить object себя с.

Если вы действительно хотите хранить указатели, вам необходимо предоставить произвольный компаратор для multiset. В C++ 11, вы можете легко сделать это с лямбда:

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

Pre-C++ 11, вы можете создать функциональный объект, который реализует operator() с тем же телом, как эта лямбда-функции.

+0

Он, вероятно, должен сделать свой 'operator <' 'const' тоже. – stardust

+0

Спасибо за ваш быстрый ответ! Да, что-то вроде этого я уже боялся ... Но решение этой проблемы должно быть решено без вставки целых объектов непосредственно в набор. Копировать полный объект в набор не очень эффективно. Особенно, если размер объектов растет. Это всего лишь прототип, и я скоро добавлю больше типов данных для своего объекта. – tom1991te

+0

@ user2372782 Я добавлю решение, если вы действительно хотите содержать указатели. Следите за редактированием. –

1

Благодарим за помощь. Это, кажется, хорошее решение для решения этой проблемы.

Я искал немного глубже в новом стандарте 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; 

Вы также можете использовать дополнительный класс для этой цели просто для сравнения, потому что в противном случае вам нужен конструктор по умолчанию, чтобы использовать этот класс таким образом.