我经常使用前向类声明和指向这些类的指针。
我现在需要通过多个层传递函数指针。我更愿意将包含声明我的函数指针原型的标头包含在取消引用函数指针的模块中,而不是包含在简单地传递该指针值的每个层中。
这可能吗?
=====
从回复中我怀疑我没有明确地表达问题。我寻求类似于前瞻性声明。我们都同意我可以写:
class foo;
void bar(foo *);
void waz(foo * p){bar(p); }
请注意,除了名称之外,waz对类foo一无所知。也许酒吧可以访问foo的完整描述。也许酒吧只会进一步传递。谁在乎?只有那些取消引用foo *的网站。所有其他网站只需要“class foo;”。
同样地,我知道我可以写:
typedef void foo(int,double);
void bar(foo *);
void waz(foo * p){bar(p); }
不同之处在于,现在标识符foo不仅已知表示函数类型,而且还已经携带完整的签名/原型。这迫使我陷入两种不愉快的情景之一:
1)在多个站点克隆typedef(哎呀!脆弱!) 2)将typedef粘贴在标题中,并将其包含在提到foo *的任何地方。
注意不对称性:在数据对象的情况下,我只需要在我想要取消引用foo *的那些点上提供类foo的完整描述;在函数的情况下,我需要在任何地方提供完整的签名/原型,我想提一个foo *。
那么无论如何要解决这种不对称问题呢?
答案 0 :(得分:4)
您可以使用未定义的结构类型执行此操作,但需要额外取消引用。
将其放在主标题文件中:
typedef struct FuncStruct *FuncPtr;
这声明struct FuncStruct
但不声明任何字段,然后它声明一个指向此结构的指针,名为FuncPtr
。您可以传递FuncPtr
,但不能取消引用它们。
然后在特定文件(或更具体的.h文件)中,您实际上可以像这样定义struct FuncStruct
:
struct FuncStruct {
int (*f)(int, char, double);
};
然后,通过此定义的代码可以取消引用FuncPtr
以获取实际的函数指针。
请注意,这只是一个演员的额外解除引用,这意味着您需要对FuncStruct
进行一些内存管理。
答案 1 :(得分:3)
对于传递函数指针,您只需要知道参数类型和返回类型:
void f(void (*func)(int));
这里,f()
是一个函数,它接受一个带int
并返回void
的函数的函数指针。
typedef
使其更具可读性:
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));
答案 2 :(得分:0)
当然,例如。
typedef void (*FOOFUNC)(int x, int y, char z);
现在你可以传递它
void foo(FOOFUNC f) {
f(...);
}
答案 3 :(得分:0)
我完全理解OP正在尝试做什么。事实上,我想做同样的事情。根据OP的说法,我有以下内容(在C中,而不是C ++):
/* File A.h */
typedef void (*f_t)(int x);
/* File B.h */
typedef void (*call_f_t)(f_t func2call,int y);
问题是,B.h
必须包含A.h
吗? A.h
定义了我不想在B.h', so I am hoping is a way to "forward reference" a function pointer, without redefining it in a typedef in
B.h`中包含的各种其他内容(这可能甚至不起作用)?
或者编译器是否需要了解f_t
中B.h
的更多内容,而不是前向引用的struct
?
我也可能需要重新考虑代码的布局,但我同意OP,在一个完美的世界中,函数指针和其他可以向前引用的对象之间应该存在某种对称性。 。
答案 4 :(得分:-1)
完全可能。您可以在任何需要的地方复制您的功能原型,但是当我看到这样做很多时,警报就会开始响起。
答案 5 :(得分:-1)
从您的问题中不清楚您要尝试做什么。
首先,C ++中没有“原型”这样的东西。 “prototype”(函数原型)的概念仅针对C语言。
其次,你在消息体中提到了一些“函数指针的原型”,而标题则讨论了“函数原型”。这使它更加令人困惑。 “函数指针的原型”毫无意义。即使在C语言中,也没有指针的“原型”,更不用说C ++了。
那么,你想做什么?如果你想转发声明一个函数 - 只需声明它。
如果要转发声明指针 - 也只是声明它。为了获得对象的声明(非定义声明),只需使用extern
关键字声明它。