我想確保一組函數在某些C代碼中具有相同的簽名。理想情況下,我將能夠定義一個描述函數的返回值和參數的新類型,然後使用這個新類型聲明我的一組函數。如何在C中的一組函數聲明上強制執行函數簽名?
此外,有沒有一種方法來指定該函數typedef的參數的默認值?
我想確保一組函數在某些C代碼中具有相同的簽名。理想情況下,我將能夠定義一個描述函數的返回值和參數的新類型,然後使用這個新類型聲明我的一組函數。如何在C中的一組函數聲明上強制執行函數簽名?
此外,有沒有一種方法來指定該函數typedef的參數的默認值?
/* define a typedef for function_t - functions that return void */
/* and take an int and char parameter */
typedef void function_t(int param1, char param2);
/* declare some functions that use that signature */
function_t foo;
function_t bar;
現在,當您定義函數時,如果它們不使用與typedef中相同的簽名,將會出現錯誤。
void foo(int x, char c)
{
/* do some stuff */
return;
}
/* this will result in a compiler error */
int bar(int x, char c)
{
/* do some stuff */
return 1;
}
至於你的新問題(添加零八年十月二十零日):「另外,有沒有爲傳遞到該函數的typedef指定默認值的方法嗎?」
不,沒有辦法將默認參數添加到typedef。當然不是在C中,它根本不支持默認參數。即使在C++中,也不能這樣做,因爲參數的默認值不是該類型的一部分。實際上,從基類中覆蓋虛擬方法的類可以爲默認參數指定不同的值(或者甚至完全刪除默認參數) - 但是,這是不應該一般地完成的,因爲它只會導致混淆(http://www.gotw.ca/gotw/005.htm)。
如果您正在使用C++,你也許能得到您想要使用的一個行爲(或組合)以下:
但它會很難提出好的建議,而無需瞭解EXAC更多的細節真正想要完成的是什麼。而且我認爲結果很可能相當不好。
這類似於一個函數指針是如何工作的:
// Declaration of function with int arg returning int
typedef int (*CALLBACK)(int);
//Definition
int myFunc(int arg)
{
return 0;
}
// Function pointer usage
CALLBACK pFunc = myFunc;
我不認爲你可以直接做到這一點,但你可以定義一個函數指針類型,然後收集所有功能集成到一個數組。編譯器會讓你知道哪些不匹配。
typedef void (*MethodSig)(int, int);
static MethodSig x[] = { fnA, fnB, ... };
或者使用宏來聲明函數簽名
#define MyFunc(X) void X(int a, int b)
這樣,他們都將是相同的。
你不能真正阻止任何人使一個函數有任何簽名。但是你可以控制你要打的電話。所以我認爲這是你想要的。
有將調用任意函數的函數以函數的指針作爲參數。既然你提到的typedef,您可以在程序中早期定義的類型定義,像這樣:
假設你只想要簽名「無符號短id_for_allowed_functions(INT X,字符* Y)」的功能:
typedef unsigned short (*id_for_allowed_functions)(int, char*);
然後,您的通話功能:
void calling_function (id_for_allowed_function x) { (*x)(3, "bla"); }
並且提供函數foo它:
unsigned short foo(int x, char* y) { /* ... */ }
calling_function(&foo);
下面是創建映射到簡單字符串的函數列表的示例。
首先是類型定義:
typedef GenList *(*DBLISTLOADER)(Database *pDB, char *quellCD, char *profilName);
typedef ObjDescription *(*DBCOLUMNLOADER)();
typedef struct dbinfo
{
char *dbName;
DBLISTLOADER dbListLoader;
DBCOLUMNLOADER dbColumnLoader;
char *options;
} DBINFO;
則映射表:
DBINFO dbInfoList[] =
{
{ "SRCDOC", loadSRCDOC, colSRCDOC, "q" },
{ "PRF_CD", loadPRF_CD, colPRF_CD, "" },
{ "MEDIA", loadMEDIA, colMEDIA, "" },
{ NULL, NULL, NULL }
};
我們從該表中查找一個函數並調用它:
while (dbInfoList[i].dbName != NULL)
{
if (strcmp(dbInfoList[i].dbName, szDatabase) == 0)
{
return (dbInfoList[i].dbListLoader)(pDB, quellCD, profilName);
}
i++;
}
很抱歉,如果它是一個有點'生'。直接從我們的代碼粘貼;-)
哇,我從來沒有那樣,只是作爲函數指針。你可以重用函數定義的function_t嗎? – quinmars 2008-10-09 18:30:33