Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
h_wolf
9 / 9 / 2
Регистрация: 24.01.2013
Сообщений: 212
1

Расскаэите о указателях на функции

18.09.2013, 15:02. Просмотров 754. Ответов 20
Метки нет (Все метки)

Всем дорого времени суток.
Объясните нубу для чего необходимы указатели на функции и как и где их правильно применять... Что-то до меня не доходит из книг.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.09.2013, 15:02
Ответы с готовыми решениями:

Об указателях
В чем разница между этими двумя строчками? int* x; int *x;

Запутался в указателях
Поиск элемента, равного figure void remove_helper(std::shared_ptr<BTreeItem>...

немного об указателях
есть код: #include <iostream> #include <windows.h> using namespace std; ...

Ошибка в указателях
Здравствуйте, не понимаю почему выводит мусор. Вроде бы все правильно сделал....

Реализация стека на указателях
Стек на указателях: #include <iostream> using std::cin; using std::cout;...

20
Raali
639 / 343 / 74
Регистрация: 06.07.2013
Сообщений: 1,107
Завершенные тесты: 1
18.09.2013, 15:08 2
для того, чтобы функцию передавать в качестве параметра другой функции, например, чтобы по таймеру выполнилась какая то твоя функция - ты передаешь ее в таймер, который написан совершенно другим человеком, и он не знает какая фукция должна выполниться после окончания таймера, а ты , в свою очередь без понятия - где и куда вставлять свою функцию в его коде, в таком случае делают функции, которые принимают в качестве параметра заведомо неизвестные функции
0
h_wolf
9 / 9 / 2
Регистрация: 24.01.2013
Сообщений: 212
18.09.2013, 15:10  [ТС] 3
почему нельзя вызвать функцию сразу после завершения функции таймер следующей строкой кода?
0
Raali
639 / 343 / 74
Регистрация: 06.07.2013
Сообщений: 1,107
Завершенные тесты: 1
18.09.2013, 15:11 4
Цитата Сообщение от h_wolf Посмотреть сообщение
после завершения функции таймер
если таймер например не ты писал и просто не знаешь куда вставлять, либо это вообще библиотека, в которой код даже не поменять будет, как например Windows для окна использует оконную процедуру, полностью заданную пользователем, которая передается в класс окна в качестве указателя
0
h_wolf
9 / 9 / 2
Регистрация: 24.01.2013
Сообщений: 212
18.09.2013, 15:15  [ТС] 5

Не по теме:

простите если туплю



Raali, Таймер функция? Почему нельзя сделать так:

C++
1
2
Timer(Amount); //заканчивается действие функции таймер
MyFunction(Arg, Arr, Tmp); //Вызывается моя функция


Указатель на функцию требуется что бы вызвать свою функцию посреди чужой функции?
0
Croessmah
++Ͻ
14610 / 8364 / 1576
Регистрация: 27.09.2012
Сообщений: 20,561
Записей в блоге: 2
Завершенные тесты: 1
18.09.2013, 15:22 6
Небольшой пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
 
template < typename T , int size >
void out_array ( const T ( & arr ) [size] ){
  for ( int i = 0 ; i < size ; ++i )
    std :: cout << arr [ i ] << " " ;
  std::cout << std::endl ;
}
 
 
 
template< class T , int size >
void bubbleSort(T ( & arr ) [size], bool (*cmp_func) ( const T & , const T & ) )
{
    T tmp;
 
    for(int i = 0; i < size - 1; ++i)
    {            
        for(int j = 0; j < size - 1; ++j)
        {     
            if ( cmp_func ( arr[j + 1] , arr[j] ) )  //Сравнение с помощью той функции, адрес которой передали. Волшебство, не правда ли? )))
            {
                tmp = arr[j + 1]; 
                arr[j + 1] = arr[j]; 
                arr[j] = tmp;
            }
        }
    }
}
 
 
 
template < typename T >
bool cmp_less ( const T & first , const T & second ) {
  return first < second ;
}
 
template < typename T >
bool cmp_great ( const T & first , const T & second ) {
  return first > second ;
}
 
 
 
int main( ) {
  int arr [] = {6,8,7,5,3,2,9,0,1,4} ;
  out_array ( arr ) ;
  bubbleSort ( arr , cmp_less ) ;
  out_array ( arr ) ;
  bubbleSort ( arr , cmp_great ) ;
  out_array ( arr ) ;
}
алгоритм сортировки взят из темы Алгоритмы сортировок
0
Raali
639 / 343 / 74
Регистрация: 06.07.2013
Сообщений: 1,107
Завершенные тесты: 1
18.09.2013, 15:25 7
Цитата Сообщение от h_wolf Посмотреть сообщение
Указатель на функцию требуется что бы вызвать свою функцию посреди чужой функции?
ну вобщем да, когда тело передаваемой функции либо не известно самой функции, либо когда тело может меняться (например функция вызова заклинания на игрока - она сама по себе не знает что это за заклинание, но инициирует его на нужного игрока, а там уже какое заклинание пользователь выбрал такой и эффект будет - либо полечит , либо подамажит)
1
h_wolf
9 / 9 / 2
Регистрация: 24.01.2013
Сообщений: 212
18.09.2013, 15:28  [ТС] 8
Croessmah, К сожаления для понимания этого примера у меня мало знаний я не знаю ни шаблонов, ни классов пока, так что Ваш пример мне не ясен...

Raali, спасибо, картинка начинает проясняться, дальше думаю сам дожую
0
Croessmah
++Ͻ
14610 / 8364 / 1576
Регистрация: 27.09.2012
Сообщений: 20,561
Записей в блоге: 2
Завершенные тесты: 1
18.09.2013, 15:40 9
Цитата Сообщение от h_wolf Посмотреть сообщение
я не знаю ни шаблонов, ни классов пока, так что Ваш пример мне не ясен...
Вот почти тоже самое без шаблонов
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
//Функция вывода массива - можно даже не смотреть
void out_array ( const int * arr , int size ){
  for ( int i = 0 ; i < size ; ++i )
    std :: cout << arr [ i ] << " " ;
  std::cout << std::endl ;
}
 
 
 
void bubbleSort ( int * arr , int size , bool (*cmp_func) ( const int & , const int & ) ) //Третий параметр - указатель на функцию, с помощью которой будут сравниваться элементы
{
    int tmp;
 
    for(int i = 0; i < size - 1; ++i)
    {            
        for(int j = 0; j < size - 1; ++j)
        {     
            if ( cmp_func ( arr[j + 1] , arr[j] ) ) //Сравниваем элементы с помощью функции, указатель на которую передали
            {
                tmp = arr[j + 1]; 
                arr[j + 1] = arr[j]; 
                arr[j] = tmp;
            }
        }
    }
}
 
 
 
bool cmp_less ( const int & first , const int & second ) {
  return first < second ;
}
 
bool cmp_great ( const int & first , const int & second ) {
  return first > second ;
}
 
 
 
int main( ) {
  const int size = 10 ;
  int arr [ size ] = {6,8,7,5,3,2,9,0,1,4} ;
  out_array ( arr , size ) ; //Вывод массива
  bubbleSort ( arr , size , cmp_less ) ; //Сортировка. Третий параметр - указатель на функцию, с помощью которой будут сравниваться элементы
  out_array ( arr , size ) ; //Смотрим результат
  bubbleSort ( arr , size , cmp_great ) ; //Опять сортируем, но теперь передаем указатель на другую функцию
  out_array ( arr , size ) ; //Смотрим теперь что получилось
  //Таким образом с помощью одной функции сортировки. мы смогли отсортировать массив и по возрастанию и по убыванию, передавая указатель на функцию сравнения элементов
}
0
User409368
191 / 168 / 32
Регистрация: 09.09.2013
Сообщений: 524
18.09.2013, 16:29 10
Допустим, есть функция F(), которая принимает 3 аргумента.
два числа типа double и указатель на другую функцию:

C++
1
2
3
4
double F(double a, double b, double (*pf)(double, double) ) 
{ 
    return pf(a, b); 
}
Эта функция в свою очередь вызывает другую через указатель (в нее передаются первые два аргумента)

Но у тебя нет исходника этой функции и ее невозможно изменить.

И тут нам нужно использовать ее в своей программе, передав третьим аргументом
свою собственную функцию Z()
C++
1
double Z(double a, double b)        { return 2*(a+b); }
Тогда мы пишем вот так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
double Z(double a, double b);
 
int main()
{
    cout << F(2.0, 3.0, Z);
 
 
    _getch();
    return 0;
}
 
 
double Z(double a, double b)        { return 2*(a+b); }
1
h_wolf
9 / 9 / 2
Регистрация: 24.01.2013
Сообщений: 212
18.09.2013, 16:47  [ТС] 11
_, Я так понимаю пример из учебника Праты?

спасибо за развернутый ответ. Я уже понял где и как это может понадобиться.
еще только одно уточнение - разве вопрос применения разных функций в разное время не решается перегрузкой функции? Или вызовом непосредственно по имени функции в коде?
0
User409368
191 / 168 / 32
Регистрация: 09.09.2013
Сообщений: 524
18.09.2013, 16:57 12
Цитата Сообщение от h_wolf Посмотреть сообщение
Я так понимаю пример из учебника Праты?
я его когда то читал, наверно из него. точно не помню ) в памяти остался

Цитата Сообщение от h_wolf Посмотреть сообщение
разве вопрос применения разных функций в разное время не решается перегрузкой функции?
да же не знаю что ответить. мне кажется это разные вещи. перегрузка это одно а передача указателя функции совсем другое. не знаю
0
h_wolf
9 / 9 / 2
Регистрация: 24.01.2013
Сообщений: 212
18.09.2013, 17:17  [ТС] 13
_, но ведь результат и цель одна и та же, или я не так понимаю?
0
Raali
639 / 343 / 74
Регистрация: 06.07.2013
Сообщений: 1,107
Завершенные тесты: 1
18.09.2013, 17:22 14
Цитата Сообщение от h_wolf Посмотреть сообщение
но ведь результат и цель одна и та же, или я не так понимаю?
в каком смысле?
0
User409368
191 / 168 / 32
Регистрация: 09.09.2013
Сообщений: 524
18.09.2013, 17:26 15
Цитата Сообщение от h_wolf Посмотреть сообщение
но ведь результат и цель одна и та же, или я не так понимаю?
нет, это все таки разные вещи. указатель это указатель, а перегрузка функций это уже другое.

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

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

C++
1
2
3
4
5
6
7
8
9
10
11
double Z(double a, double b);
 
double F(double a, double b, double (*pf)(double, double) );
 
int main()
{
    double (*pf)(double, double); // pf - это указатель на функцию
 
    pf = Z; // указателю присвоили адрес на функцию Z
 
    // здесь можно этому указателю присвоить адрес другой функции. но только на функцию, которая возвращает значение double и принимает два аргумента, каждый из которых double
1
h_wolf
9 / 9 / 2
Регистрация: 24.01.2013
Сообщений: 212
18.09.2013, 17:38  [ТС] 16
Raali,
Цитата Сообщение от Raali Посмотреть сообщение
Сообщение от h_wolf
но ведь результат и цель одна и та же, или я не так понимаю?
в каком смысле?
в том что бы вызывать в зависимости от ситуации разные функции, нет?

_, не ясно почему нельзя вызвать функцию явно, зачем усложнять указателями?
0
Croessmah
++Ͻ
14610 / 8364 / 1576
Регистрация: 27.09.2012
Сообщений: 20,561
Записей в блоге: 2
Завершенные тесты: 1
18.09.2013, 17:49 17
Цитата Сообщение от h_wolf Посмотреть сообщение
зачем усложнять указателями?
Наоборот всё становится легче
0
ValeryS
Модератор
7262 / 5516 / 692
Регистрация: 14.02.2011
Сообщений: 18,676
18.09.2013, 17:51 18
Цитата Сообщение от h_wolf Посмотреть сообщение
в том что бы вызывать в зависимости от ситуации разные функции, нет?
и в этом тоже
например есть функции сортировки, она берет указатель на массив и указатель на функцию сравнения (больше меньше)
в массиве могут лежать не простые данные(int char) а например твоя структура
тогда пишешь свою функцию сравнения и подсовываешь функции сортировки
итого одна и та же функция может сортировать разные данные

второе применение, есть функция которая лежит в DLL подгружая DLL ты можешь взять адрес нужной тебе функции и использовать её по указателю.
1
Raali
639 / 343 / 74
Регистрация: 06.07.2013
Сообщений: 1,107
Завершенные тесты: 1
18.09.2013, 17:51 19
Цитата Сообщение от h_wolf Посмотреть сообщение
не ясно почему нельзя вызвать функцию явно, зачем усложнять указателями?
xD

вот например нам надо чтобы по кнопке ESC мы выходили из программы, к сожалению это не виндоус и мы не можем отследить нажатие клавиши сами, за то у нас есть одна функция в библиотеке по работе с клавиатурой вида - SetKeyboardListener(kbfunc f); - Она сама (мы не знаем, и не сможем узнать когда) вызовет пользовательскую(нашу) функцию обработки клавиш, тогда когда она посчитает нужным(в момент нажатия клавиши например)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void listener(int param)
{
if(param == ESC)
{
exit(1);
}
}
 
int main(int, char**)
{
SetKeyboardListener(listener);
 
while(1) ;
 
return 1;
}
1
h_wolf
9 / 9 / 2
Регистрация: 24.01.2013
Сообщений: 212
18.09.2013, 18:05  [ТС] 20
Спасибо всем, за подробные ответы, видимо так туго идет понимание из-за отсутствия опыта.
0
18.09.2013, 18:05
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.09.2013, 18:05

Об указателях по философски-математически
Допустим, имеем код: int *p; Есть мнение, что истолковать запись можно...

Совсем запутался в указателях
Шестую строку не могу понять, по моему перед массивом var должен стоять &amp;....

Реализация очереди на указателях
Очередь на указателях: #include &lt;iostream&gt; using std::cin; using...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru