2011-05-25 228 views
7

如何聲明一個函數指針指向一個函數,該函數採用與參數相同的函數指針?函數指針指向一個函數指針的函數

我已經嘗試沒有成功如下:

typedef void (*fnptr)(void (*)()); 

void func(fnptr) 
{ 
    /* ... */ 
} 

void func2(fnptr) 
{ 
    /* ... */ 
} 

void main() 
{ 
    fnptr fn = &func; 
    func2(fn); 
} 

這可能嗎?

+1

林不知道,它會像努力模板化與自身的東西,你就結束了一個遞歸聲明 – 2011-05-25 17:23:55

+0

我倒認爲它不能做。 – 2011-05-25 17:23:57

+2

如何使用泛型聲明和顯式強制轉換? – casablanca 2011-05-25 17:24:48

回答

13

我非常懷疑它,但是您可以通過引入結構來獲得所需的遞歸。使用

struct Rec; 

typedef void (*RecFun)(const Rec&); 

struct Rec { 
    RecFun fun; 
}; 

例子:

#include <iostream> 

void nothing(const Rec& rec) {} 
Rec recNothing = { nothing }; 

void f(const Rec& rec) 
{ 
    std::cout << "f\n"; 
    rec.fun(recNothing); 
} 
Rec recF = { f }; 

void g(const Rec& rec) 
{ 
    std::cout << "g\n"; 
    rec.fun(recNothing); 
} 
Rec recG = { g }; 

int main() 
{ 
    recF.fun(recG); 
} 

更新:每克里斯,維特斯,和Johannes的建議作爲,這裏有一些方便的隱式轉換(如香草薩特的GotW #57):

struct Rec; 

typedef void (*RecFun)(const Rec&); 

struct Rec { 
    RecFun fun; 
    Rec(RecFun fun) : fun(fun) {} 
    operator RecFun() const { return fun; } 
}; 
+1

+1用於管理遞歸問題的優雅方法。 – dusktreader 2011-05-25 17:36:02

+1

如果你喜歡語法 – 2011-05-25 17:45:37

+0

完美的答案,你甚至可以重寫'operator()',使它看起來和行爲像一個函數(函子)。非常感謝! :D – 2011-05-25 18:04:21

0

最簡單的方法就是敲入兩者。一個函數指針就像任何其他類型的參數:

typedef (* InnerFunctionPtr)(void); 
typedef (* OuterFunctionPtr)(InnerFunctionPtr); 

編輯:鄉親們都指出你的意思是既要爲同一類型。在這種情況下,這是不可能的,因爲類型是遞歸的。創建完整的類型規範是不可能的(函數參數的類型從未完全指定,ergo ...)

+2

我認爲OP意味着相同類型的論點。 – casablanca 2011-05-25 17:22:24

+0

'OuterFunctionPtr'將不得不採用'OuterFunctionPtr'作爲參數。 – 2011-05-25 17:25:30

+0

-1。錯誤的typedef! – Nawaz 2011-05-25 17:32:06

0

唉,不能這樣做。如果你可以使用typename轉發聲明一個typedef,那將是很好的;是這樣的:

typename fnptr; 
typedef (*fnptr)(fnptr); 

但是,這並不工作,因爲typename僅限於幾個特定的​​模板使用

0

有可能以這種方式:

typedef void (*fnptr)(void (*)()); 

fnptr fn1,fn2; 
void func(fn1) 
{ 
/* ... */ 
} 

void func2(fn2) 
{ 
/* ... */ 
} 
void main() 
{ 
fnptr fn = &func; 
func2(fn); 
} 
0

您也可以打敗類型系統通過假裝該函數採用其他函數指針類型,然後在您將某些內容傳遞給該函數並在該函數內部獲取原始類型時將其轉換。

不推薦顯然,但只是把它放在那裏。如果你能

typedef void (*fnptr)(void (*)()); 

void func(void (*x)()) 
{ 
    fnptr f = (fnptr)x; 
    /* ... */ 
} 

void func2(void (*x)()) 
{ 
    fnptr f = (fnptr)x; 
    /* ... */ 
} 

void main() 
{ 
    fnptr fn = &func; 
    func2((void (*)())fn); 
}