在C++中使用函数typedef定义函数

4

我正在Windows上实现一个服务。Visual Studio 2012有以下函数类型定义:

typedef VOID WINAPI SERVICE_MAIN_FUNCTIONW (
    DWORD dwNumServicesArgs,
    LPWSTR *lpServiceArgVectors
);

还有一个函数指针类型定义:

typedef VOID (WINAPI *LPSERVICE_MAIN_FUNCTIONW)(
    DWORD   dwNumServicesArgs,
    LPWSTR  *lpServiceArgVectors
);

如何使用typedef定义具有此函数签名的函数?
5个回答

8
引用当前的C++标准(C++11):
[dcl.fct]/10

A typedef of function type may be used to declare a function but shall not be used to define a function (8.4). [Example:

typedef void F();
F fv;             // OK: equivalent to void fv();
F fv { }          // ill-formed
void fv() { }     // OK: definition of fv

—end example ]

也就是说,您可以使用 typedef 声明函数但不定义函数。您必须显式指定函数签名,参见 Alex Farber 的答案。


在某种程度上,您可以使用 typedef 来“定义”函数,但这涉及到一些模板魔法。这只是一个有趣的例子,展示了您实际上可以使用它来定义函数。

// extra definitions for SSCCE
  typedef unsigned int DWORD;
  typedef wchar_t* LPWSTR;
  #define VOID void
  #define WINAPI

// function ptr
typedef VOID (WINAPI *LPSERVICE_MAIN_FUNCTIONW)(
    DWORD   dwNumServicesArgs,
    LPWSTR  *lpServiceArgVectors
);

// function typedef
typedef VOID WINAPI SERVICE_MAIN_FUNCTIONW (
    DWORD dwNumServicesArgs,
    LPWSTR *lpServiceArgVectors
);


template < typename... TT >
struct disassemble_funcptr
{};
template < typename Ret, typename... Args >
struct disassemble_funcptr < Ret(Args...) >
{
    typedef Ret return_type;

    static Ret Func(Args...)
    {
        /* your code here */
    }
};

// using the typedef SERVICE_MAIN_FUNCTIONW to define the function
LPSERVICE_MAIN_FUNCTIONW my_func_ptr =
  & disassemble_funcptr < SERVICE_MAIN_FUNCTIONW > :: Func;

int main()
{
    LPWSTR str = nullptr;
    my_func_ptr(42, &str);
}

4

使用C++11,您可以利用空捕获列表的lambda表达式可转换为函数指针的事实,在一个表达式中声明和定义与函数typedef相匹配的函数,例如:

using my_function_t = void(*)(int,int);

my_function_t add_function = [](int x, int y) { return x + y; };

1

使用 typedef 无法定义(或声明)函数。必须以传统方式定义函数。例如:

void foo (type1 t1, type2 t2) // t1 and t2 are objects which can be ... 
{                             // ... visible only in conventional way
  ...
}

函数指针typedef可以声明函数指针,该指针可以被分配为函数的地址:

typedef void (*PF)(type1, type2);
PF pf = &foo;

3
如果我没有完全错的话,可以声明一下,看看我的回答。 - dyp
1
正如@DyP所说,您可以使用适当的typedef声明一个函数(问题中的第一个示例),但是您正确地指出,您不能使用typedef定义一个函数(而DyP也没有建议您可以定义一个函数)。 - Jonathan Leffler
是的,我的编译器也同意你们两个的观点 - 它可以被声明但不能被定义。 - chowey
@JonathanLeffler,@Dyp(对答案点个赞),没错我已经编辑了答案。不过,typedef声明能否完全替代常规声明(例如,默认参数)? - iammilind

1
你不需要(也不能)在函数定义中使用typedef。要创建一个服务主函数,只需编写以下代码:
VOID WINAPI SvcMain( DWORD dwNumServicesArgs, LPWSTR *lpServiceArgVectors )
{
    // ...
}

LPSERVICE_MAIN_FUNCTIONW是Windows内部用来调用每个服务启动点的函数。通常情况下,你需要使用函数指针typedef来调用,而不是定义一个函数。


0

可以通过反转尝试的方法来实现。

  • 定义一个宏,该宏扩展为所需的类型
#define defLedClkFunc(name)   void (name)(uint16_t led)
  • 使用宏定义你的typedef
typedef defLedClkFunc(tLedClkFunction);
  • 在声明函数实现时使用宏
//********************************************************
//
// Declaration of first function
//
defLedClkFunc(ledClkEnable)
{
  // Body of first function
} // ledClkEnable()

//********************************************************
//
// Declaration of second function
//
defLedClkFunc(ledClkDisable)
{
  // Body of second function
} // ledClkDisable()

//
// Create an array of pointers to the functions
//
tLedClkFunction *myFuncs[] = {
                             ledClkEnable,
                             ledClkDisable,
                             };

现在你有一个函数签名的单点定义,对签名的任何更改都会传播到所有的类型定义和函数声明中。
我发现这对于定义一组函数(例如中断处理程序、消息处理程序)非常有用。
此外,宏使得修改 *所有 函数名称变得非常简单,如果有人决定它们都应该具有某个任意前缀和/或后缀。只需在宏定义中使用标记粘贴,并将所需的前缀/后缀粘贴在 name 周围即可。
你需要记住创建的数据类型以便操作指向这些函数的指针,但即使那样也可以通过少量的额外宏魔法来自动适应。

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