函数指针typedef的语法是什么?

6

我正在研究线程池,为了避免使用过长的限定符名称,我想使用 typedef 声明。

但事实并不像看起来那么简单:

typedef unsigned ( __stdcall *start_address )( void * ) task;

当我尝试那种方式时,我得到了:
error C3646: 'task' : unknown override specifier

错误,在使用这个声明进行一段时间后,我卡住了,找不到任何合理的解决方案来声明这种类型的 typedef


1
“task”应该是什么意思?它是一些特殊的关键字吗? - PlasmaHH
任务是我想用来替代这个冗长的声明的词。但没关系,问题已经找到解决方法了。感谢大家,特别是pb2q :) - unresolved_external
请注意:实现一个相当不错的线程池远非易事。您是否考虑使用现有的实现? - Paul Michalik
好吧,这是为了教育目的,所以我想我会冒险 :) - unresolved_external
@unresolved_external: 你没有想过 start_address 是用来干什么的吗? - PlasmaHH
3个回答

15

当创建一个函数指针的typedef别名时,别名就在函数名称位置,因此使用:

typedef unsigned (__stdcall *task )(void *);

task现在是一个类型别名, 表示指向一个函数的指针, 该函数接受一个 void 指针并返回一个 unsigned 值。


@unresolved_external 如果这个答案是解决你问题的最佳方案(从你的评论来看似乎是),请不要忘记接受它。 - Christian Rau
@unresolved_external:在C语言中忘记函数指针语法并不是什么可耻的事情:D - Ed S.
那真糟糕...我喜欢C++,但是指针和常量的语法真的很让人头疼。 - Youda008

7

由于hmjd的答案已被删除...

C++11开发了全新的别名语法,使这些操作更加容易:

using task = unsigned (__stdcall*)(void*);

等价于 typedef unsigned (__stdcall* task)(void*);(注意别名在函数签名中间的位置...)。

它也可以用于模板:

template <typename T>
using Vec = std::vector<T>;

int main() {
    Vec<int> x;
}

这个语法比旧的更好(对于模板而言,实际上可以实现模板别名),但需要一个相当新的编译器。


0
附注:在不同的编译器/编译器设置下,__stdcall 部分可能会破坏您的代码(除非函数也被明确声明为 __stdcall)。我建议只使用专有编译器扩展来保持默认调用约定,并且必须有充分的理由。

或者使用一个宏,将其#define__stdcall 或其他取决于编译器的内容。尽管通常只在与具有定义调用约定的(通常是特定于平台的)库进行交互时才显式声明调用约定。 - Adam Rosenfield

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接