Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20

Указатели на функции (Прата) - не пойму, как это работает

16.07.2014, 17:42. Показов 3403. Ответов 28
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Стивен Прата "Язык программирования C++. Лекции и упражнения"
7 глава, стр. 355, листинг 7.18. fun_ptr.cpp

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
// fun_ptr.cpp -- pointers to functions
#include <iostream>
double betsy(int);
double pam(int);
 
// second argument is pointer to a type double function that
// takes a type int argument
void estimate(int lines, double (*pf)(int));
 
int main()
{
    using namespace std;
    int code;
 
    cout << "How many lines of code do you need? ";
    cin >> code;
    cout << "Here's Betsy's estimate:\n";
    estimate(code, betsy);
    cout << "Here's Pam's estimate:\n";
    estimate(code, pam);
    // cin.get();
    // cin.get();
    return 0;
}
 
double betsy(int lns)
{
    return 0.05 * lns;
}
 
double pam(int lns)
{
    return 0.03 * lns + 0.0004 * lns * lns;
}
 
void estimate(int lines, double (*pf)(int))
{
    using namespace std;
    cout << lines << " lines will take ";
    cout << (*pf)(lines) << " hour(s)\n";
}
Вопрос. Я как бы понял, что в прототипе функции можно написать только типы
аргументов, опустив имена; либо написать те самые имена, которые будут в
реализации функции; либо вовсе написать любые удобные имена, которые будут
служить своеобразной подсказкой - это не важно, компилятор всё равно эти имена
пропустит.
В прототипах функций betsy() и pam() указаны только типы аргументов, это я
понял. В прототипе функции estimate() указаны имена-подсказки lines и pf
соответственно. Несмотря на то, что нигде потом не будет объявлена переменная
int lines и указатель pf, компилятор понимает, что первым аргументом функции
estimate() должно быть целое число, либо целочисленная переменная (в нашем
случае - переменная int code), а вторым аргументом указатель на функцию (в нашем
случае это betsy и pam, соответственно). Понимает почему? Потому что при вызове
функции estimate() на месте int lines стоит int code, а на месте double (*pf)(int) стоит
betsy (или во втором вызове - pam).
Но я хоть убей не могу понять, каким волшебным образом компилятор понимает,
что переменная int lns - это та же самая int code. Откуда он берёт это знание?
С чего он вообще решил, что надо подставить вместо int lns переменную int code?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.07.2014, 17:42
Ответы с готовыми решениями:

Не пойму, куда и как вставить функции и указатели
Дан массив из N чисел. Найти наибольший элемент массива и поменять его местами с наименьшим элементом. #include&lt;iostream.h&gt; ...

Не пойму как это работает
PS C:\User&gt; (Get-ChildItem -Path &quot;C:\tmp\002&quot;) | Get-Member (Get-ChildItem -Path &quot;C:\tmp\002&quot;).Count Get-Member : Укажите...

Прата и умные указатели
Читаю Прата С. - Язык программирования С++. Лекции и упражнения - 2011, стр. 886: Пишу, компилирую - получаю ошибки: Кто не прав...

28
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
19.07.2014, 22:55
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от gru74ik Посмотреть сообщение
Функции разные, имена переменных разные, а адрес у обеих один и тот же!
Точнее чем сказано здесь, вряд ли можно ответить. Я думаю все со мной согласятся, что этот ответ лучший, и тебе нужно просто вникнуть в него.
1
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.07.2014, 03:26
Цитата Сообщение от gru74ik Посмотреть сообщение
Не понятно почему переменная в betsy() и переменная в pam() - это одна и та же переменная? Функции разные, имена переменных разные, а адрес у обеих один и тот же!
почему одна и та же? Можешь разными назвать, это ничего не поменяет:
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
// fun_ptr.cpp -- pointers to functions
#include <iostream>
double betsy(int);
double pam(int);
 
void estimate(int lines, double(*pf)(int));
 
int main()
{
    using namespace std;
    int code;
 
    cout << "How many lines of code do you need? ";
    cin >> code;
    cout << "Here's Betsy's estimate:\n";
    estimate(code, betsy);
    cout << "Here's Pam's estimate:\n";
    estimate(code, pam);
    return 0;
}
 
double betsy(int x)
{
    return 0.05 * x;
}
 
double pam(int y)
{
    return 0.03 * y + 0.0004 * y * y;
}
 
void estimate(int lines, double(*pf)(int))
{
    using namespace std;
    cout << lines << " lines will take ";
    cout << pf(lines) << " hour(s)\n";
}
можешь даже функции разного типа сделать, все равно работать будет:
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
// fun_ptr.cpp -- pointers to functions
#include <iostream>
double betsy(int);
double pam(double);
 
template <typename FuncPtr>
void estimate(int lines, FuncPtr);
 
int main()
{
    using namespace std;
    int code;
 
    cout << "How many lines of code do you need? ";
    cin >> code;
    cout << "Here's Betsy's estimate:\n";
    estimate(code, betsy);
    cout << "Here's Pam's estimate:\n";
    estimate(code, pam);
    return 0;
}
 
double betsy(int x)
{
    return 0.05 * x;
}
 
double pam(double y)
{
    return 0.03 * y + 0.0004 * y * y;
}
 
template <typename FuncPtr>
void estimate(int lines, FuncPtr pf)
{
    using namespace std;
    cout << lines << " lines will take ";
    cout << pf(lines) << " hour(s)\n";
}
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
20.07.2014, 13:22  [ТС]
Цитата Сообщение от Psilon Посмотреть сообщение
почему одна и та же?
То есть один и тот же адрес - просто дело случая? А переменные int lns в функции betsy() и int lns в функции pam(), как и положено, разные?
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
20.07.2014, 13:40
Лучший ответ Сообщение было отмечено gru74ik как решение

Решение

Цитата Сообщение от gru74ik Посмотреть сообщение
А переменные int lns в функции betsy() и int lns в функции pam(), как и положено, разные?
Честно говоря, не понимаю, в чем вообще затруднение в понимании.
Существование фактических аргументов функции (вышеупомянутые переменные) разнесено по времени.
И нет совершенно никак объективных причин, почему бы не использовать ту же самую память (с одинаковыми адресами) в разные моменты времени.

Вызовите одну функцию из другой и увидите, что адреса будут разные. А всё потому, что они уже используются (должны существовать) одновременно.
1
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
20.07.2014, 14:20  [ТС]
Цитата Сообщение от Tulosba Посмотреть сообщение
Существование фактических аргументов функции (вышеупомянутые переменные) разнесено по времени.
И нет совершенно никак объективных причин, почему бы не использовать ту же самую память (с одинаковыми адресами) в разные моменты времени.
То, что требовалось! Покорнейше благодарю, всё встало на свои места.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
20.07.2014, 15:27
gru74ik, да, в нём тоже.

Добавлено через 19 минут
Psilon, всегда считал и сейчас считаю что разницы нет, т.к. вызвать функцию через указатель можно только одним способом в конечном итоге.
2
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.07.2014, 16:44
Tulosba, эмм, что? Вот вызовы по-очереди, адреса все равно разные. Изменяем этот метод:
C++
1
2
3
4
5
6
template <typename FuncPtr>
void estimate(int lines, FuncPtr pf)
{
    using namespace std;
    cout << "Func adress is\t" << pf << endl;
}
получаем:
C++
1
2
3
4
5
6
How many lines of code do you need? 10
Here's Betsy's estimate:
Func adress is  001310E1
Here's Pam's estimate:
Func adress is  001312F3
Для продолжения нажмите любую клавишу . . .
как бы разные адреса жеж. Или я неправильно вопрос понял
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
20.07.2014, 20:21
Psilon, когда я писал ответ на вопрос ТС из сообщения #23 я опирался на код из сообщения #6. В частности на строки 37 и 48.
Т.е. речь об адресах фактических аргументов функций, которые (аргументы) будут на стеке.
1
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.07.2014, 21:35
Tulosba, а, ну это логично. В принципе, если один поток всегда у процесса, то тогда первый аргумент будет всегда иметь один и тот же адрес для всех функций
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.07.2014, 21:35

Указатели на функции. Указатели на функции как формальные параметры у функциях высшего уровня
Найти наименьшее значение для функций используя функции и указатели на функции ...

Не пойму как это
Сломался блок распределения питания. Я должен щас купить новый и завтра с ним поехать устанавливать. Прислали фотки и я не могу понять одну...

Битовая арифметика в параметрах функции. Как это работает?
Разбираюсь с библиотекой SDL http://ru.wikipedia.org/wiki/Simple_DirectMedia_Layer Там есть такая функция int SDL_Init(Uint32 flags); ...

Никак не пойму, как это сделать
Значения элементов двумерного массива из m строк и n столбцов скопировать в одномерный массив размером m n. Копирование проводить: по...

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


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

Или воспользуйтесь поиском по форуму:
29
Ответ Создать тему
Новые блоги и статьи
Часы с термометром и праздничным календарем
yariko 12.11.2026
Сегодня мы рассмотрим как можно сделать отличные многофункциональные часы. Итак, поставим конкретную задачу: разработать часы с календарем, двумя термодатчиками, выводом поздравительных сообщений. . .
Транслитерация текста с кириллицы на латиницу (вариант №1)
Maks 11.11.2026
Решил облегчить жизнь себе и коллегам админам при создании электронных почтовых ящиков для пользователей, в результате написал обработку "Транслитерация текста" с кириллицы на латиницу, а в ней. . .
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru