использование typedef для переноса функций

Один из моих учителей использует это объявление типа:

typedef void (*SortFunction)(int a[], int n);

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

Я также знаю, что для передачи функции в качестве параметра вы должны
оберните имя функции в круглые скобки и оберните
параметры в скобках после имени функции, а также так

function someFunction( (anotherfunction)(type arg1, type arg2,...)){
...
}

Я хочу знать, почему вы должны заключать в скобки функцию, подобную этой? это встроенная функция большинства компиляторов с ++ или это просто хитрость, которую мы, программисты, используем
для того, чтобы включить функции в качестве аргументов в нашем коде? Кроме того, почему необходимо ссылаться на «SortFunction» в операторе typedef, почему переменная, которую вы используете для использования SortFunction, просто хранит функцию вместо того, чтобы указывать на нее?

0

Решение

В аргументах функции нет ничего особенного. Всякий раз, когда вы объявляете указатель на функцию (как локальную переменную, глобальную переменную, переменную-член класса, параметр функции, typedef и т. Д.), Он всегда объявляется так:

return_type (*var_name)(T1 param1, T2 param2, /* etc. */ );
//           ^
//           |
// This * is very important!

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

Вы не можете передать функцию в качестве аргумента, потому что функции не являются первоклассными объектами в C и C ++. Единственный способ передать функцию — это передать указатель на функцию.

1

Другие решения

Это вопрос синтаксиса. Ты первый typedef определяет тип, который является функцией, получающей вектор int и int и ничего не возвращая (void).

Переменная типа SortFunction будет концептуально как любая другая переменная, хотя она указывает на некоторую функцию. Преимущество состоит в том, что вы можете изменить функцию, на которую она указывает, и / или вызвать функцию динамически.

0

Я хочу знать, почему вы должны заключать в скобки функцию, подобную этой?

Потому что должен был быть какой-то способ идентифицировать указатель на функцию компилятора (точнее, парсера), и этот путь казался таким же хорошим, как и любой другой. В земле C ++ 11 вы можете использовать это вместо: std::function<void(std::array<int>&)> вместо.

это встроенная функция большинства компиляторов c ++ или это просто уловка, которую мы, программисты, используем для включения функций в качестве аргументов в нашем коде?

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

Кроме того, почему необходимо ссылаться на «SortFunction» в операторе typedef, почему переменная, которую вы используете для использования SortFunction, просто хранит функцию вместо того, чтобы указывать на нее?

Хм. Не совсем уверен, что вы имеете в виду здесь. Ты имеешь ввиду «почему это должно быть typedef вообще … почему я не могу просто написать прототип целого указателя функции в аргументах своей функции«? Вы можете:

void foo(void(*funcptr)()) {}

Если бы вы имели в видупочему указатели на функции должны указывать на функцию, а не на встроенный код«Тогда для этого вам нужны C ++ 11 и лямбды:

#include <iostream>
#include <functional>

void foo(std::function<void(void)> bar) { bar(); }

int main(int argc, char* argv[])
{
foo([]() { std::cout << "hi!" << std::endl; });
}

(опять же, специальный синтаксис, необходимый для лямбд, [](){}просто чтобы разобрать парсер что происходит)

0

«Я также знаю, что для передачи функции в качестве параметра необходимо заключить имя функции в круглые скобки …» Вы «знаете» неправильно.

Чтобы передать указатель на функцию в качестве параметра, вам не нужно заключать имя в скобки. Например, это будет отлично работать

void foo(int i) {
}

void bar(void f(int)) {
f(5);
}

int main() {
bar();
}

В приведенном выше примере функции bar получает указатель на функцию foo в качестве параметра и вызывает foo через этот указатель, передавая 5 в качестве аргумента. Как видите, имя функции f в объявлении параметра есть не в скобках.

В этом случае, еще раз, тип параметра f на самом деле указатель для функции, даже если она явно не объявлена ​​как указатель. Когда тип функции используется в объявлениях параметров функции, он автоматически неявно «заменяется» типом указателя на функцию компилятором.

Если вы хотите явно использовать тип указателя на функцию, вы должны объявить bar как

void bar(void (*f)(int)) {
f(5);
}

В этом случае скобки в (*f) необходимо гарантировать, что * будет связан с f и не void, Без скобок void *f(int) объявление будет означать «возвращение функции void *«вместо желаемого» указатель на функцию, возвращающую void».

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector