簡體   English   中英

在 C++ 中使用函數 typedef 定義函數

[英]Defining a function using a function typedef in C++

我正在 Windows 中實現一項服務。 VisualStudio 2012 具有以下函數 typedef:

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

還有一個函數指針typedef:

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

如何使用 typedef 定義具有此函數簽名的函數?

引用當前的 C++ 標准 (C++11):

[dcl.fct]/10

函數類型的 typedef 可用於聲明函數,但不得用於定義函數(8.4)。 [例子:

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

—結束示例]

也就是說,您可以使用該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);
}

不能使用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;

您不需要(也不能)在函數定義中使用 typedef。 要使服務主函數,只需編寫:

VOID WINAPI SvcMain( DWORD dwNumServicesArgs, LPWSTR *lpServiceArgVectors )
{
    // ...
}

LPSERVICE_MAIN_FUNCTIONW由 Windows 內部用於調用每個服務起點。 通常,您需要函數指針typedef來調用,而不是定義函數。

使用 C++11,您可以利用具有空捕獲列表的 lambda 表達式可轉換為函數指針這一事實來聲明和定義與一個表達式中的函數 typedef 匹配的函數,例如:

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

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

這可以通過反轉嘗試的方法來實現。

  • 定義一個擴展為所需類型的宏
#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周圍粘貼所需的前綴/后綴。

確實需要記住為操作指向函數的指針而創建的數據類型,但即使這樣也可以通過少量額外的宏魔法進行自動調整。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM