Синтаксис typedef с указателями на функции-члены - PullRequest
23 голосов
/ 07 июня 2011

в соответствии с MSDN синтаксис typedef:

typedef синоним объявления типа;

Очень просто:

typedef int MY_INT;

Но как, черт возьми, указатели на функции-указатели-члены соответствуют этому правилу?

typedef int (MyClass::*MyTypedef)( int);

100% путаница - синоним (MyTypedef) посередине?

Может кто-нибудь объяснить, какие логические шаги нужно выполнить от очень простого для понимания формата синтаксиса MSDN до вещи с обратным / случайным / передним / последним / смешанным синтаксисом, приведенной выше typedef?

* изменить спасибо за быстрые ответы (и украшение моего поста):)

Ответы [ 9 ]

37 голосов
/ 07 июня 2011

синоним (MyTypedef) находится в середине ??

Его нет в середине.Просто на время забудьте функцию-член, посмотрите, как определяется указатель на функцию:

int (*FuncPtr)(int);

И вот как вы могли бы ее определить:

typedef int (*FuncPtr)(int); 

Просто!Единственная разница в том, что typedef FuncPtr становится type , тогда как в объявлении указателя FuncPtr является переменная .

Аналогично,

int (MyClass::*MyTypedef)( int); //MyTypedef is a variable

И typedef как:

typedef int (MyClass::*MyTypedef)( int); //MyTypedef is a type!
17 голосов
/ 10 марта 2016

Стоит отметить, что начиная с C ++ 11 вы могли бы написать это выражение как более разборчивое using выражение:

using MyTypedef = int (MyClass::*)(int);
10 голосов
/ 07 июня 2011

Как вы определяете указатель на функцию-член?Например:

int (A::*variableName)(int);

Чтобы сделать это typedef, просто добавьте typedef:

typedef int (A::*typedefName)(int);
4 голосов
/ 07 июня 2011

Я знаю, что вы уже получили свой ответ, но хотите поделиться этим - это удобно: http://www.cdecl.org. Это объявление C / C ++ <-> английский переводчик.Просто введите

, объявите x как указатель на член функции класса A (int), возвращающей char

, и вы получите char (A::*x)(int ).Или поиграйте с декларацией и посмотрите, получите ли вы то, что хотите.

4 голосов
/ 07 июня 2011

Принцип объявления в C ++ заключается в том, что они имитируют использование. Если вы хотите использовать указатель на функцию-член pmf, вы напишите:

(myVar.*pmf)(arg);

чтобы определить для него typedef, вы пишете:

typedef int (MyClass::*pmf)(int);

добавление возвращаемого типа в заголовок, замена переменной типом и аргументы их типом.

3 голосов
/ 20 августа 2017

Синтаксис использования указателя на функцию-член должен (предположим, a является экземпляром класса A):

  • в объявлении, используйте "A ::" в качестве префикса
  • при использовании используйте «а».в качестве префикса

Ниже приведен пример с игрушкой.Вы можете играть с ним.

#include <stdio.h>
#include <stdlib.h>
class A;
typedef int (A::*F)(double);

class A {
 public:
  int funcDouble(double x) { return (int)(x * 2.0); }
  int funcTriple(double x) { return (int)(x * 3.0); }

  void set(int a) {
    if (a == 2) {
      this->f_ = &A::funcDouble;
    } else if (a == 3) {
      this->f_ = &A::funcTriple;
    } else {
      this->f_ = NULL;
    }
  }

 public:
  F f_;
};
int main(int argc, char *argv[]) {
  A a;
  a.set(2);
  F f = &A::funcDouble;
  printf("double of 1 = %d\n", (a.*f)(1));

  // Below is equivalent to:
  // F f2 = a.f_;
  // printf("double of 1 = %d\n", (a.*f2)(1));
  printf("double of 1 = %d\n", (a.*(a.f_))(1));

  a.set(3);
  printf("triple of 1 = %d\n", (a.*(a.f_))(1));

  return 0;
}
1 голос
/ 07 июня 2011

Страница, на которую вы ссылаетесь, вероятно, " Спецификатор типа ". Упрощенный синтаксис "typedef type-declaration synonim;" - это только один из многих способов использования typedef. Нет (возможно) простого и краткого способа описать, как можно использовать typedef. Для этого предназначена страница MSDN " декларации типов ".

Вы заметите на этой странице что-то вроде:

declaration: 
    declaration-specifiers init-declarator-list opt ; 
declaration-specifiers: 
    storage-class-specifier declaration-specifiers opt 
    type-specifier declaration-specifiers opt
    type-qualifier declaration-specifiers opt 
storage-class-specifier: 
    typedef

Подробнее о том, какие спецификации объявлений и список инициализации объявлений можно найти здесь .

Это один строгий способ понять все возможные варианты использования "typedef".

На этой странице в основном говорится, что typedef можно использовать перед большинством допустимых объявлений.

1 голос
/ 07 июня 2011

Однажды я прочитал хорошее объяснение (но оно из Ожидайте программирования на C , поэтому я ymmv):

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

Поскольку typedef выглядит точно так же, как объявление переменной, она читается точно как один. Вместо декларация "это имя относится переменной указанного типа, " Ключевое слово typedef не создает переменная, но вызывает объявление сказать "это имя является синонимом указанный тип. "

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

0 голосов
/ 07 июня 2011

Будет легче понять, когда вы начнете думать так:

Всякий раз, когда вы видите такую ​​функцию:

TYPE foo(int arg1, int arg2);

Вы говорите, что тип foo - ТИП. Итак, тип

int get_next_prime();

это int.

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

void register_callback(void (*ptr)(int));

В этом случае вы передаете функцию типа void в качестве аргумента.

Теперь, когда вы видите что-то подобное:

typedef int (A::*typedefName)(int);

вы просто говорите, что переменная (A :: * typedefName) (int) (это только одно, а не два, поскольку это объявление указателя функции) на самом деле имеет тип int. С этого момента компилятор будет интерпретировать A :: * typedefName как функцию типа int, то есть он возвращает значение int.

Надеюсь, это сделает его менее запутанным.

...