Объявление указателя функции typedef в C ++ - PullRequest
3 голосов
/ 15 октября 2019

Я понимаю, что подобные вопросы с ответами задавались ранее. Я уже понимаю концепцию указателя функции и смысл ее объявления. Ниже приведен пример кода указателя функции, в котором я назначаю указатель функции fp_GetBiggerElement, указывающий на функцию GetBiggerElement

    #include <iostream>

    typedef     int     (*fp_GetBiggerElement)      (int, int);
    //           ^                ^                     ^
    //      return type      type name              arguments

    using namespace std;

    int GetBiggerElement(int arg1, int arg2)
    {
        int bigger = arg1 > arg2 ? arg1 : arg2;
        return bigger;
    }

    int main()
    {
        fp_GetBiggerElement funcPtr = GetBiggerElement;

        int valueReturned = funcPtr(10, 20);
        cout << valueReturned << endl;
        return 0;
    }

Что я понимаю, typedef означает предоставление нового определениядля типа. Обычно для оператора typedef требуется two-parts (или, скажем, два аргумента)

  1. первая часть - это тип, который нуждается вновый псевдоним

  2. вторая часть - это новое имя псевдонима

    typedef     unsigned  int       UnsignedInt;
    //              ^                   ^                       
    //          (original type)     (Alias)
    

, напримерв приведенном выше коде первая часть - unsigned int, а вторая - UnsignedInt

    typedef     char *              CharPtr;
    //              ^                   ^                       
    //      (original type)          (Alias)

аналогично, во втором примере выше первая часть - char*, а вторая часть -CharPtr

ВОПРОС: Я запутался в FORMAT оператора typedef для указателя на функцию. В операторе typedef int(*fp_GetBiggerElement)(int, int); типичный формат с двумя аргументами для typedef не используется тогда, как он работает?

ОБНОВЛЕНИЕ: Я знаю, что C ++ 11 предлагаетдругой способ объявить указатель на функцию т.е. (using statment). В этом вопросе меня интересует только синтаксис оператора typedef для указателя функции.

Ответы [ 5 ]

6 голосов
/ 15 октября 2019

Я думаю, что лучшая идея думать о синтаксисе typedef - это как объявить переменную типа, который вы хотите ввести typedef. Например:

char *CharPtr;// declare CharPtr to be variable of type char*

typedef char *CharPtr_t;// declare CharPtr_t to be alias of type char*

Аналогично с указателями функций:

int (*fp) (int, int);// declare fp as pointer to int(int, int)

typedef int (*fp_t)(int, int);// declare fp_t to be alias of pointer to int(int, int)

Кстати, в C ++ 11 и далее вы получаете не слишком запутанную (и более мощную) альтернативу typedef - using. Вы должны использовать (каламбур) вместо этого. Просто посмотрите:

using fp = int (*)(int, int);// declare fp_t to be alias of pointer to int(int, int)
4 голосов
/ 15 октября 2019

typedef использует тот же синтаксис, что и объявление переменной, но объявляет имя типа, а не имя переменной.

Части «перемешаны» несколько своеобразным (некоторые называют это «wtf?») Способом - объявление переменной имеет ту же форму, что и его использование, что упрощает синтаксический анализатор и позволяет повторно использовать код в компиляторе,

Это имеет больше смысла, если вы читаете более "старой школой":

int *p;

"*p - это int"
(Эквивалентный перевод: "p - указатель на int ")

int *p, x;

" *p и x оба int s "
(" p - указатель на int и x - это int ")

int (*q)[3];

" *q - это массив из трех int s ", или" (*q)[x] - это int "
("q - указатель на массив из трех int с")

int (*fp)(int,int);

"*fp - это функция, которая принимает два int с и возвращает int"
("fp - указатель на функцию, которая принимает два int s и возвращает int")

int (*(*foo)())[3];

"*(*foo)() - это массив из трех ints "(альтернативно," (*(*foo)())[x] - это int) - или, другими словами,
"(*foo)() - указатель на массив из трех int s" - или, другими словами,
"foo - указатель на функцию, которая не принимает аргументов и возвращает указатель на массив из трех int s"

. Немного нечитаемый эффект этого состоит в том, что

int *p, x, (*q)[3], (*fp)(int,int), (*(*foo)())[3];

объявляет все вышеперечисленное сразу.

3 голосов
/ 15 октября 2019

Это просто синтаксис для указателей на функции. Вы бы увидели то же самое, если бы просто объявили переменную.

int foo; // Normal
int (*bar)(int, int); // bar is of type int(*)(int,int)

Лично я предпочитаю использовать using = ..., что, на мой взгляд, более понятно.

using fp_GetBiggerElement = int (*)(int,int);
1 голос
/ 15 октября 2019

Этот синтаксис происходит из C-способа чтения переменных.

Когда-нибудь задумывались, зачем нам звездочка, для каждого указателя, который мы хотим объявить в одном выражении?

int *p1, *p2, p3; // p3 is not a pointer

Люди на C ++ обычно склонны видеть переменную определенного типа, которая может быть указателем (другими словами, они видят характеристики указателя как свойство типа ). Вот почему они обычно предпочитают писать

int* p1; // notice asterisk grouped with type

C, а люди читают как: у меня есть переменная p1, и если я разыменую ее, я получаю тип int (поэтому p1, будучи указателем, выводит информацию, то есть они видят характеристики указателя скорее как свойство переменной , и поэтому они скорее группируют звездочку по имени: int *p1;).

Очень похоже на указатели на функции:

int (*fp) (int, int);

У меня есть переменная fp, и если я разыменую ее, я получу int (int, int). То же самое, что и для typedef. С другой стороны, (новый) способ определения псевдонима в C ++ намного лучше отражает мышление C ++:

using fp = int (*)(int, int);

У меня есть переменная, и ее тип является указателем (на что угодно) прямо изначало - ну, не совсем последовательно, хотя: при мышлении C ++ указатели на функции могут скорее выглядеть как int(int, int)* или, возможно, требовать скобки (int(int, int))*, но ОК, это не так (желание оставаться совместимым с Cявляясь поводом для этого).

0 голосов
/ 15 октября 2019

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

Рассмотрим следующие примеры простых объявлений

int x;
unsigned int a[10][20];
int unsigned ( *p )[10][20];
void ( *f )( int, int );
double h( double ); 

Они объявляют несколько объектов и функцию h.

Теперь поместите в эти объявления спецификатор decl typedef (в любом порядке относительнодругим спецификаторам decl), и вы получите, что объявленные идентификаторы становятся псевдонимами типов.

typedef int x;
unsigned typedef int a[10][20];
int unsigned typedef ( *p )[10][20];
void typedef ( *f )( int, int );
typedef double h( double ); 

То есть x является псевдонимом типа int. a - это псевдоним типа unsigned int [10][20]. p - псевдоним для типа указателя unsigned int ( * )[10][20]. f - псевдоним для указателя функции void ( * )( int, int ). И h в псевдониме для функции типа double( double ).

...