Я делаю регулярное использование объявлений класса переадресации и указателей на такие классы.
У меня теперь есть потребность передать указатель функции через многие слои. Я предпочел бы включать заголовок, который объявляет прототип моего указателя функции только в модуль, который разыменовывает указатель функции, а не на каждый слой, который просто проводит то значение указателя.
Действительно ли это возможно?
=====
От ответов я подозреваю, что не выразил вопросом достаточно ясно. Я ищу аналог на объявление класса переадресации. Все мы соглашаемся, что я могу записать:
нечто класса;
пустая панель (нечто*);
освободите waz (нечто* p) {панель (p);}
Заметьте, что waz ничего не знает о нечто класса кроме его имени. Возможно, панель будет иметь доступ к полному описанию нечто. Возможно, панель просто передаст p далее вперед.Какая разница? Только те сайты, которые разыменовывают foo*. Всем другим сайтам нужно только "нечто класса";.
Так же я знаю, что могу записать:
определение типа пустое нечто (интервал, дважды);
пустая панель (нечто*);
освободите waz (нечто* p) {панель (p);}
Различие - то, что теперь нечто идентификатора не только, как известно, обозначает функциональный тип, но и далее уже несет полную подпись/прототип. Это вынуждает меня в один из двух неприятных сценариев:
1) клонируйте определение типа на нескольких сайтах (фу! хрупкий!) 2) засовывают определение типа в заголовок и включают его везде, что нечто* упоминается.
Заметьте асимметрию: в случае объекта данных я только должен был предоставить полное описание нечто класса в тех точках, где я хочу разыменовать нечто*; в случае функции я должен обеспечить полную подпись/прототип везде, я хочу упомянуть foo*.
Так там должен так или иначе исправить эту асимметрию?
Для передачи указателей функций вам нужно знать только типы аргументов и тип возвращаемого значения:
void f(void (*func)(int));
Здесь f ()
функция, которая принимает указатель на функцию, которая принимает int
и возвращает void
.
typedef
s делают это более читаемым:
typedef void (*FuncPtr)(int);
void f(FuncPtr func);
В общем, вы можете посмотреть на функторы или использовать, например, Boost.Function и Boost.Bind . Таким образом, вы также можете передавать связанные функции-члены или объекты функций:
void f(boost::function<void (int)> fn) {
fn(42);
}
struct X {
void f(int) {}
};
// ...
X x;
f(boost::bind(&X::f, &x, _1));
Вполне возможно. Вы можете скопировать свой прототип функции где угодно, хотя, когда я вижу, что это делается много, начинают срабатывать тревожные звонки.
Вы можете сделать это, используя неопределенный тип структуры, за счет дополнительного разыменования.
поместите это в главный файл заголовка:
typedef struct FuncStruct *FuncPtr;
Это объявляет структуру FuncStruct
, но не объявляет никаких полей, затем объявляется указатель на эту структуру с именем FuncPtr
. Вы можете передавать FuncPtr
, но не можете разыменовать их.
то в конкретном файле (или более конкретном файле .h) вы можете определить структуру struct FuncStruct
следующим образом:
struct FuncStruct {
int (*f)(int, char, double);
};
Затем код после этого определения может разыменовать FuncPtr
, чтобы получить фактический указатель функции.
Обратите внимание, что это дополнительное разыменование от простого приведения, и это означает, что вам нужно будет немного управлять памятью FuncStruct
s.
Конечно, например
typedef void (*FOOFUNC)(int x, int y, char z);
Теперь вы можете передать его вокруг
void foo(FOOFUNC f) {
f(...);
}
Из вашего вопроса неясно, что вы пытаетесь сделать.
Во-первых, в C ++ нет такого понятия, как «прототип». Понятие «прототип» (прототип функции) характерно только для языка C.
Во-вторых, вы упоминаете некий «прототип указателя функции» в теле сообщения, а заголовок говорит о «прототипе функции». Это еще больше сбивает с толку. «Прототип указателя на функцию» не имеет смысла. Нет такого понятия, как «прототип» для указателя, даже в C, не говоря уже о C ++.
Итак, что вы хотите сделать? Если вы хотите объявить функцию вперед - просто объявите ее.
Если вы хотите объявить указатель вперед, просто объявите его. Чтобы получить объявление (не определяющее объявление) объекта, просто объявите его с помощью ключевого слова extern
.