Как передать функцию обратного вызова члену класса? - PullRequest
1 голос
/ 14 ноября 2011

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

Мне нужно передать функцию сравнения в конструктор класса, предопределенную функцию сравнения дляЗатем ints и тому подобное оставляют за клиентом возможность предоставлять любые функции сравнения, которые могут ему понадобиться.Но как мне это сделать?

template<typename Type>
int cmpFn(Type one, Type two)
{
    if (one < two) return -1;
    if (one > two) return 1;
    return 0;
}

template <typename Type>
class Queue
{
    public:
        Queue()
        {
            Type *list = new Type[size];
            // What do I do now?
            // How to define this constructor?
            // It must pass a comparison function
            // to a private sort method in this class.
        }
    private:
        void sortFunc(Type list, int(fn)(Type one, Type  two)=cmpFn);
};

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

Это личное упражнение, я не зачислен ни на один курс и не имею доступа к каким-либо преподавателям,Я уже некоторое время гуглю это, но не могу придумать правильный ответ ... Наверное, я не задавал правильный вопрос мистеру Гуглу.

PS Клиент можетЯ хочу предоставить функции сравнения для любых данных, например:

struct individual
{
    string name;
    int age;
    double height;
};

Я предполагаю, что конструктор должен быть таким:

Queue(int (*fn)(Type, Type) = cmpFn);

Но как мне определить / реализовать это?Этот объект обратного вызова будет использовать не сам объект Queue, а его метод: sort ();

Ответы [ 2 ]

2 голосов
/ 14 ноября 2011

Вот рабочий, компилируемый пример того, что, я думаю, вам нужно:

#include <cstddef>
#include <string>
#include <iostream>

template<typename Type>
int cmpFn(Type one, Type two)
{
    if (one < two) return -1;
    if (one > two) return 1;
    return 0;
}

template <typename Type>
class Queue
{
    public:
        // This is the typedef for your callback type
        typedef int (*callback)(Type one, Type two);

        Queue(Type *list, size_t size, callback func = cmpFn)
        {
            sortFunc(list, size, func); // works too
        }

    private:
        void sortFunc(Type *list, size_t size, callback func) {
            for (size_t i=0; i<size; i++) {
                for (size_t j=0; j<size; j++) {
                    if (i == j) continue;

                    int val = (*func)(list[i], list[j]);
                    switch (val) {
                        case 1:
                            std::cout << list[i] << " is greater than " << list[j] << "\n";
                            break;
                        case -1:
                            std::cout << list[j] << " is greater than " << list[i] << "\n";
                            break;
                        case 0:
                            std::cout << list[i] << " and " << list[j] << " are equal\n";
                            break;
                    }
                }
            }
        }

};

int stringCmp(std::string one, std::string two) {
    if (one.size() < two.size()) return -1;
    if (one.size() > two.size()) return 1;
    return 0;
}

int main() {
    // compare ints, use generic comparison function (cmpFn)
    int myInts[2] = {1, 2};
    Queue<int> qi(myInts, 2);

    // compare strings, use our own comparison function (stringCmp)
    std::string myStrings[2] = {"foo", "bar"};
    Queue<std::string> qs(myStrings, 2, stringCmp);

    return 0;
}

Компиляция и выполнение программы, приведенной выше, должны дать вам такой вывод:

2 is greater than 1
2 is greater than 1
foo and bar are equal
bar and foo are equal

В основном то, что он делает:

  • Конструктор Queue принимает массив list, его размер и функцию обратного вызова.
  • Если функция обратного вызова не предоставлена, он использует универсальную функцию (cmpFn).
  • Затем вызывается sortFunc, который просматривает все элементы в массиве list и сравнивает их, используя функцию обратного вызова.

В приведенном выше кодеу вас есть пример с int и std::string.

0 голосов
/ 14 ноября 2011

Может быть так:

void sortFunc(Type list, int(*fn)(Type one, Type  two) = cmpFn<Type>);

Вероятно, лучше передать аргументы по const-ссылке, а не по копии. Кто знает, могут ли они быть скопированы?

...