Определение указателя на функцию
Чтобы определить указатель на функцию, которая не имеет аргументов и не возвращает значения, вы говорите:
void (*funcPtr)();
Когда вы смотрите на такое сложное определение, лучший способ атаковать его - начать с середины и найти выход. «Начать с середины» означает начинать с имени переменной, которая называется funcPtr. «Выходя из положения» означает поиск справа ближайшего предмета (ничего в данном случае; правая скобка не останавливает вас), затем взгляд влево (указатель, обозначенный звездочкой), затем взгляд вправо ( пустой список аргументов, указывающий на функцию, которая не принимает аргументов), затем смотрит влево (void, что указывает на то, что функция не имеет возвращаемого значения). Это движение вправо-влево-вправо работает с большинством объявлений.
Чтобы просмотреть, «начните с середины» («funcPtr - это ...»), перейдите направо (ничего нет - вас остановили правые скобки), перейдите влево и найдите «*» (« ... указатель на ... »), перейдите вправо и найдите пустой список аргументов (« ... функция, не принимающая аргументов ... »), перейдите влево и найдите пустоту (« funcPtr is указатель на функцию, которая не принимает аргументов и возвращает void »).
Вы можете задаться вопросом, почему * funcPtr требует скобок. Если вы их не используете, компилятор увидит:
void *funcPtr();
Вы бы объявили функцию (которая возвращает void *) вместо определения переменной. Вы можете думать о компиляторе как о прохождении того же процесса, что и вы, когда он выясняет, каким должно быть объявление или определение. Ему нужно, чтобы эти круглые скобки «натолкнулись на», поэтому он возвращается влево и находит «*» вместо продолжения вправо и поиска пустого списка аргументов.
Сложные декларации и определения
Кроме того, как только вы поймете, как работает синтаксис объявлений C и C ++, вы можете создавать гораздо более сложные элементы. Например:
//: C03:ComplicatedDefinitions.cpp
/* 1. */ void * (*(*fp1)(int))[10];
/* 2. */ float (*(*fp2)(int,int,float))(int);
/* 3. */ typedef double (*(*(*fp3)())[10])();
fp3 a;
/* 4. */ int (*(*f4())[10])();
int main() {} ///:~
Пройдите через каждый и используйте правую-левую направляющую, чтобы выяснить это. Номер 1 говорит: «fp1 - указатель на функцию, которая принимает целочисленный аргумент и возвращает указатель на массив из 10 пустых указателей».
Номер 2 говорит: «fp2 - это указатель на функцию, которая принимает три аргумента (int, int и float) и возвращает указатель на функцию, которая принимает целочисленный аргумент и возвращает float».
Если вы создаете много сложных определений, вы можете использовать typedef. Номер 3 показывает, как typedef сохраняет ввод сложного описания каждый раз. В нем говорится: «fp3 - это указатель на функцию, которая не принимает аргументов и возвращает указатель на массив из 10 указателей на функции, которые не принимают аргументов и возвращают double». Затем он говорит «а является одним из этих типов fp3». typedef обычно полезен для создания сложных описаний из простых.
Номер 4 - это объявление функции вместо определения переменной. В нем говорится: «f4 - это функция, которая возвращает указатель на массив из 10 указателей на функции, которые возвращают целые числа».
Вам редко понадобятся такие сложные объявления и определения, как эти. Однако, если вы выполните упражнение по их выяснению, вы даже не будете слегка обеспокоены слегка сложными, с которыми вы можете столкнуться в реальной жизни.