Функция сравнения, используемая функцией qsort(), сопоставляя два элемента массива, должна возвратить отрицательное значение, если ее первый аргумент указывает на значение, которое меньше второго, нуль, если эти аргументы равны, и положительное значение, если первый аргумент указывает на значение, которое больше второго.
Чтобы понять, как можно использовать функцию qsort(), рассмотрим следующую программу.
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
int comp(const void *a, const void *b);
int main()
{
char str[] = "Указатели на функции дают гибкость.";
qsort(str, strlen(str), 1, comp);
cout << "Отсортированная строка: " << str;
return 0;
}
int comp(const void *a, const void *b)
{
return * (char *) a - * (char *) b;
}
Вот как выглядят результаты выполнения этой программы.
Отсортированная строка: Уаааабгдезииииккклнностттуфцью
Эта программа сортирует строку str в возрастающем порядке. Поскольку функции qsort() передается вся необходимая ей информация, включая указатель на функцию сравнения, ее можно использовать для сортировки данных любого типа. Например, следующая программа сортирует массив целых чисел. Для гарантии переносимости при определении размера целочисленного значения в ней используется оператор sizeof.
#include <iostream>
#include <cstdlib>
using namespace std;
int comp(const void *a, const void *b);
int main()
{
int num[] = {10, 4, 3, 6, 5, 7, 8};
int i;
qsort(num, 7, sizeof(int), comp);
for(i=0; i<7; i++)
cout << num[i] << ' ';
return 0;
}
int comp(const void *a, const void *b)
{
return * (int *) a - * (int *) b;
}
He стану утверждать, что указатели на функции не так просты для понимания, но практика поможет и "с ними найти общий язык". В отношении указателей на функции необходимо рассмотреть еще один аспект, связанный с перегруженными функциями.
Получить адрес перегруженной функции немного сложнее, чем найти адрес обычной "одиночной" функции. Если же существует несколько версий перегруженной функции, то должен существовать механизм, который бы определял, адрес какой именно версии мы получаем. При получении адреса перегруженной функции именно способ объявления указателя определяет, адрес какой ее версии будет получен. По сути, объявление указателя в этом случае сравнивается с соответствующими объявлениями указателей перегруженных функций. Функция, объявление которой обнаружит совпадение, и будет той функцией, адрес которой мы получили.
В следующем примере программы содержится две версии функции space(). Первая версия выводит на экран count пробелов, а вторая— count символов, переданных в качестве аргумента ch. В функции main() объявляются два указателя на функции. Первый задан как указатель на функцию с одним целочисленным параметром, а второй — как указатель на функцию с двумя параметрами.
/* Использование указателей на перегруженные функции.
*/
#include <iostream>
using namespace std;
// Вывод на экран count пробелов.
void space(int count)
{
for( ; count; count--) cout << ' ';
}
// Вывод на экран count символов, переданных в ch.
void space(int count, char ch)