Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20

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

16.07.2014, 17:42. Показов 3278. Ответов 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
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,830
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
Ответ Создать тему
Опции темы

Новые блоги и статьи
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru