Синтаксис синтаксиса функции 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.
Как я могу напечатать только подпись?
Ответы
Ответ 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, не стандартизированный...