Почему эта программа перегружена () оператором? - PullRequest
4 голосов
/ 08 октября 2010

В настоящее время я изучаю стандартную библиотеку шаблонов (STL).

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

Код:

#include <iostream>
#include <set>
#include <functional>

using namespace std;

class UnitLess
{
public:
    bool operator()(long first, long second)
    {
        long fu = first % 10;
        long su = second % 10;

        return fu < su;
    }
};

typedef set<long, UnitLess> Ctnr;

int main(void)
{
    Ctnr store;

    store.insert(3124);
    store.insert(5236);
    store.insert(2347);
    store.insert(6415);
    store.insert(4548);
    store.insert(6415);

    for(Ctnr::iterator i = store.begin(); i != store.end(); ++i)
    {
        cout << *i << endl;
    }
}

Но я не понимаю, почему наш профессор перегружен оператором ()?

Спасибо.

Ответы [ 3 ]

7 голосов
/ 08 октября 2010

Цель этого класса - реализовать функцию, которая сортирует элементы в наборе заданным способом. Это известно как предикат.

Он реализован как функтор, т. Е. Позволяет использовать оператор функции на объекте (это то, что делает std :: set под капотом). Это является обычным способом для STL и аналогичного кода вызывать пользовательские объекты. (Указатель на функцию более ограничен, чем функциональный объект (a.k.a. functor)

Так что он используется так:

Unitless functor;

functor(123, 124); // returns true or false

std :: set является отсортированным двоичным деревом, поэтому он вызывает оператор (без) Unitless несколько раз при каждой вставке, чтобы определить, куда должно идти каждое длинное значение.

Попробуйте скомпилировать и поместить туда printf / std :: cout и посмотрите, что получится.

Кроме того, имейте в виду, что подобные обратные вызовы (то есть, когда вы не видите вызов своего кода) страшны и запутаны в начале вашей кривой обучения.

  • Тогда вы привыкаете к этому и используете их повсюду, потому что они аккуратны.
  • Тогда ваш код снова становится страшным и запутанным, и вы избегаете их, как чума.
  • Тогда вы становитесь программистом на клейкой ленте и используете их только там, где это необходимо, но никогда в другом месте.
* * Тысяча двадцать-одина;) * * тысяча двадцать две
7 голосов
/ 08 октября 2010

UnitLess - это двоичный предикат , который требуется для вызова с двумя параметрами в STL.

Путем перегрузки оператора вызова функции в UnitLess экземпляры этого типа можно использовать как функцию, которая принимает два longs и возвращает bool.

UnitLess f;
f(5, 10);

эквивалентно

bool f(long first, long second)
{
    long fu = first % 10;
    long su = second % 10;

    return fu < su;
}
f(5, 10);
2 голосов
/ 08 октября 2010

Он реализовал пользовательское сравнение, используемое для std :: set, которое сравнивает только единицы, то есть сумму по модулю 10. Поскольку std :: set является шаблоном, он просто пытается вызвать что-то, похожее на функцию, независимо от того, является ли онаэто один или нет.Перегружая operator (), вы заставляете его действовать как функция.

В некоторых случаях это может быть очень мощным, потому что структура / класс может хранить состояние, а также дополнительные параметры.Все, что делает boost :: function / boost :: bind, основано на этом (и вам не нужно каждый раз создавать класс).

В самом закодированном примере, возможно, есть небольшой недостаток:упражнение состояло в том, чтобы просто отсортировать их по единицам, но это вполне могло бы устранить числа, которые имеют одинаковые единицы, но на самом деле не являются дубликатами.В вашем примере кода таких примеров нет (у вас есть дубликат, но это дубликат всего значения).Если бы у вас было 3478 в дополнение к 4548, компаратор множеств считал бы их одинаковыми и не разрешил бы дублирование.

Кстати, я не уверен, что set - это то, что я бы назвал «ассоциативным» контейнером,который относится к парам ключ-значение.В наборе нет связанных значений, только ключи.

Еще один момент: operator () должен быть постоянным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...