Указатели на функции — различия между версиями
(Новая страница: «Указатели на функции в С++ Одно из отличие С и С++ - в С++ есть перегрузка. Тогда получается F f =…») |
(→Указатели на функции в С++) |
||
| (не показано 7 промежуточных версий 3 участников) | |||
| Строка 1: | Строка 1: | ||
| − | Указатели на функции в С++ | + | == Указатели на функции в С == |
| − | Одно из | + | Рассмотрим метод qsort, который имеет прототип: |
| − | F f = qsort; // | + | <source lang="cpp"> |
| + | void qsort(void *base, size_t nmemb, size_t size, | ||
| + | int (*compare)(const void *, const void *)); | ||
| + | </source> | ||
| + | где | ||
| + | <source lang="cpp"> | ||
| + | int (*compare)(const void *a, const void *b) | ||
| + | </source> | ||
| + | указатель на функцию, которая имеет 2 параметра, и возращает значение: | ||
| + | * > 0, если a > b | ||
| + | * = 0, если a == b | ||
| + | * < 0, если a < b | ||
| + | |||
| + | Рассмотрим пример: | ||
| + | <source lang="cpp"> | ||
| + | struct Person { | ||
| + | int m_age; | ||
| + | } | ||
| + | </source> | ||
| + | Создадим объект структуры Person. | ||
| + | <source lang="cpp"> | ||
| + | Person *m; | ||
| + | qsort(m, count, sizeof(Person), &(byage)); | ||
| + | </source> | ||
| + | |||
| + | Определим функцию byage: | ||
| + | <source lang="cpp"> | ||
| + | int byage(void const *p1, void const *p2) { | ||
| + | return ((Person *)p1)->age - ((Person *)p2)->age; | ||
| + | } | ||
| + | </source> | ||
| + | |||
| + | Замечание: | ||
| + | |||
| + | В С нет проверки типов. | ||
| + | |||
| + | Замечание: | ||
| + | * При объявлении указателя на функцию можем не писать параметры, то есть | ||
| + | <source lang="cpp"> | ||
| + | int(*)(void const *, void const *); | ||
| + | </source> | ||
| + | * Можно присвоить указателю на функцию значение 0 | ||
| + | <source lang="cpp"> | ||
| + | void (*f)(void *, size_t , size_t , int (*)(const void *, const void *)) = 0; | ||
| + | </source> | ||
| + | При этом для таких конструкций можно использовать typedef <...>, где второе имя не будет указано, так как в его роли выступит f в левой части выражения. | ||
| + | * Присваивание | ||
| + | <source lang="cpp"> | ||
| + | f = &qsort; | ||
| + | </source> | ||
| + | * Вызов | ||
| + | <source lang="cpp"> | ||
| + | f(m, count, sizeof(Person), &byage); | ||
| + | </source> | ||
| + | |||
| + | == Указатели на функции в С++ == | ||
| + | |||
| + | Одно из отличий С и С++ - в С++ есть перегрузка. Тогда получается | ||
| + | <source lang="cpp"> | ||
| + | F f = qsort; // должна вызываться та, что подойдет лучше всего | ||
| + | </source> | ||
Вопрос: | Вопрос: | ||
| + | |||
Как происходит работа с шаблонными функциями? | Как происходит работа с шаблонными функциями? | ||
| + | |||
Ответ: | Ответ: | ||
| − | |||
| + | Рассмотрим два примера. | ||
| + | |||
| + | Пример 1: | ||
| + | |||
| + | <source lang="cpp"> | ||
| + | template <class It, class F> void A(It p, It q, F f); | ||
| + | A(v.begin(), v.end(), (int(*)(int))sqrt); // необходимо приведение типов | ||
| + | </source> | ||
| + | |||
| + | Пример 2: | ||
| + | <source lang="cpp"> | ||
| + | template <class T> T sqrt(T *); | ||
| + | </source> | ||
| + | Нам необходимо проинстанциировать функцию, для этого существует несколько способов: | ||
| + | *<source lang="cpp"> | ||
| + | sqrt(0); | ||
| + | </source> | ||
| + | *<source lang="cpp"> | ||
| + | template sqrt<int>; // явно для T = int | ||
| + | </source> | ||
| + | В результате, метод A мы можем вызывать: | ||
| + | <source lang="cpp"> | ||
| + | A(v.begin(), v.end(), sqrt<int>); | ||
| + | </source> | ||
Вопрос: | Вопрос: | ||
| Строка 12: | Строка 97: | ||
Ответ: | Ответ: | ||
Рассмотрим пример: | Рассмотрим пример: | ||
| + | <source lang="cpp"> | ||
struct Person { | struct Person { | ||
int m_age; | int m_age; | ||
| Строка 20: | Строка 106: | ||
} | } | ||
} | } | ||
| + | </source> | ||
| + | |||
Тогда | Тогда | ||
| + | <source lang="cpp"> | ||
int Person::(*p) = &Person::m_age; | int Person::(*p) = &Person::m_age; | ||
string (Person::*f)() const = &Person::name; | string (Person::*f)() const = &Person::name; | ||
| + | </source> | ||
Далее имеем | Далее имеем | ||
| + | <source lang="cpp"> | ||
Person pers; | Person pers; | ||
(pers.*p) = 10; | (pers.*p) = 10; | ||
(pers.*f)(); | (pers.*f)(); | ||
| + | </source> | ||
Вопрос: | Вопрос: | ||
| − | Мы имеем указатель на | + | |
| + | Мы имеем указатель на член класса. Можем ли мы его передавать как параметр функции? | ||
| + | |||
Ответ: | Ответ: | ||
| − | |||
| + | Да, можем. Пример, | ||
| + | |||
| + | <source lang="cpp"> | ||
struct by_field { | struct by_field { | ||
by_field(int Person::*field) | by_field(int Person::*field) | ||
} | } | ||
| + | </source> | ||
Замечание: | Замечание: | ||
| − | Указатели на | + | Указатели на члены класса не приводяться ни к чему. Они могут проверяться на равенство 0. |
Текущая версия на 02:35, 11 июня 2012
Указатели на функции в С
Рассмотрим метод qsort, который имеет прототип:
void qsort(void *base, size_t nmemb, size_t size,
int (*compare)(const void *, const void *));
где
int (*compare)(const void *a, const void *b)
указатель на функцию, которая имеет 2 параметра, и возращает значение:
- > 0, если a > b
- = 0, если a == b
- < 0, если a < b
Рассмотрим пример:
struct Person {
int m_age;
}
Создадим объект структуры Person.
Person *m;
qsort(m, count, sizeof(Person), &(byage));
Определим функцию byage:
int byage(void const *p1, void const *p2) {
return ((Person *)p1)->age - ((Person *)p2)->age;
}
Замечание:
В С нет проверки типов.
Замечание:
- При объявлении указателя на функцию можем не писать параметры, то есть
int(*)(void const *, void const *);
- Можно присвоить указателю на функцию значение 0
void (*f)(void *, size_t , size_t , int (*)(const void *, const void *)) = 0;
При этом для таких конструкций можно использовать typedef <...>, где второе имя не будет указано, так как в его роли выступит f в левой части выражения.
- Присваивание
f = &qsort;
- Вызов
f(m, count, sizeof(Person), &byage);
Указатели на функции в С++
Одно из отличий С и С++ - в С++ есть перегрузка. Тогда получается
F f = qsort; // должна вызываться та, что подойдет лучше всего
Вопрос:
Как происходит работа с шаблонными функциями?
Ответ:
Рассмотрим два примера.
Пример 1:
template <class It, class F> void A(It p, It q, F f);
A(v.begin(), v.end(), (int(*)(int))sqrt); // необходимо приведение типов
Пример 2:
template <class T> T sqrt(T *);
Нам необходимо проинстанциировать функцию, для этого существует несколько способов:
sqrt(0);
template sqrt<int>; // явно для T = int
В результате, метод A мы можем вызывать:
A(v.begin(), v.end(), sqrt<int>);
Вопрос: Как получить указатели на члены класса? Ответ: Рассмотрим пример:
struct Person {
int m_age;
int m_salary;
string m_name;
string name() {
return m_name;
}
}
Тогда
int Person::(*p) = &Person::m_age;
string (Person::*f)() const = &Person::name;
Далее имеем
Person pers;
(pers.*p) = 10;
(pers.*f)();
Вопрос:
Мы имеем указатель на член класса. Можем ли мы его передавать как параметр функции?
Ответ:
Да, можем. Пример,
struct by_field {
by_field(int Person::*field)
}
Замечание: Указатели на члены класса не приводяться ни к чему. Они могут проверяться на равенство 0.