Подтвердить что ты не робот

Синтаксис синтаксиса функции typedef Си ++

Я хочу объявить определение типа для сигнатуры функции-члена. Глобальные функции typedefs выглядят следующим образом:

typedef int (function_signature)(int, int);
typedef int (*function_pointer) (int, int);

Но я не могу использовать одно и то же для функции-члена:

typedef int (foo::memberf_signature)(int, int);   // memberf_pointer is not a member of foo
typedef int (foo::*memberf_pointer)(int, int);

Звучит логично для меня, потому что "foo::" ist синтаксис для доступа к члену в классе foo. Как я могу напечатать только подпись?

4b9b3361

Ответ 1

Для вопросов, касающихся неуклюжего синтаксиса указателя на функцию, я лично использую шпаргалку: Учебное пособие по указателям на функции (скачивается здесь, спасибо Vector за указание).

Однако, как вы уже видели, подпись функции-члена немного отличается от подписи обычной функции.

Как вы, вероятно, знаете, функция-член имеет скрытый параметр this, тип которого необходимо указать.

// C++11 and above.
using Member = int (Foo::*)(int, int);

// C++03 and below.
typedef int (Foo::*Member)(int, int);

позволяет вам указать, что первый элемент, переданный функции, будет Foo* (и, следовательно, ваш метод действительно принимает 3 аргумента, когда вы об этом думаете, а не только 2).

Однако есть и другая причина, заставляющая вас указать тип.

Указатель на функцию может ссылаться на виртуальную функцию, и в этом случае все может быть довольно сложно. Следовательно, сам размер представления в памяти изменяется в зависимости от типа функции. Действительно, в Visual Studio размер указателя на функцию может варьироваться от 1 до 4 раз больше, чем обычный указатель. Это зависит от того, является ли функция виртуальной, в частности.

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

Ответ 2

Вы можете отчислить целевой класс в современном С++ (post 11), используя 'typedefing' качества псевдонимов шаблонов. То, что вам нужно, будет выглядеть следующим образом:

template<typename T>
using memberf_pointer = int (T::*)(int, int); 

Однако в точке объявления указатель на функцию-член, использующий этот синтаксис, должен указать целевой класс:

// D is a member function taking (int, int) and returning int
memberf_pointer<foo> mp = &foo::D; 

Ответ 3

Это работает для меня:

#include <iostream>

class foo
  {
public:
  int g (int x, int y) { return x + y ; }
  } ;

typedef int (foo::*memberf_pointer)(int, int);

int main()
  {
  foo f ;
  memberf_pointer mp = &foo::g ;
  std::cout << (f.*mp) (5, 8) << std::endl ;
  }

Ответ 4

Причина, по которой он не работает с вашим текущим синтаксисом, заключается в том, что приоритет оператора указывает на то, что вы ссылаетесь на функцию с именем foo::memberf_signature, а не на какой-либо тип.

Я не знаю точно, могу ли вы это сделать или нет, но я не мог придумать какую-либо комбинацию parenthese, которая побуждала код компилироваться с g++ 4.2.

Ответ 5

Ну в принципе он не может работать (по крайней мере, я не знаю, как использовать g++); С помощью компилятора borland С++ будет ключевое слово __closure.

Причина, по которой он не компилируется, заключается в том, что размер функции-указателя (на машине x86) всегда занимает < < 32bits → ; но если вы хотите указать на подпись класса (интерфейса), sizeof должен быть 64 бит: 32 бит для этого указателя (поскольку интерфейс класса находится в памяти только один раз) и 32 бит для фактической функции

Но ключевое слово __closure - это "hack" на языке bcb, не стандартизированный...