首先,你不用C語言編程。你用C++編程。這是一種不同的語言。 C沒有引用或類。在你的代碼中,你不使用類,但是你使用了一個引用(無理由)。
其次,考慮「函數指針」的含義。它是該函數的代碼地址。現在考慮「內聯」的含義。這意味着該功能在機器代碼中不是獨立存在的。它的來源是(概念上)放在它被調用的地方,並且調用函數被編譯。所以你想採取不存在的東西的地址。
簡短的回答是你不能。
你想實現什麼?你想總是從b打電話給foo嗎?如果是這樣,你不需要間接。您可以調用內聯函數並將其內聯到呼叫站點,也可以調用非內聯函數併產生實際的函數調用。
// a.c
double foo(int a) { return a * 3.1415926; }
// b.c
double foo(int a); // declaration, not definition.
void b(void) { printf("%f\n", foo(10)); }
int main() { b(); return 0; }
建設有: gcc -O2 -c -o a.o a.c
注意,編譯b.c時,編譯器不知道什麼函數foo做,只知道它的簽名。 gcc -O2 -c -o b.o b.c
這兩塊連接成一個單一的程序,並增加在開始和結束時,使它們能夠運行它的部分: gcc -o program a.o b.o
不同的是效率。內聯允許進行許多優化(直到使用參數的值預先計算結果並完全消除代碼,如此處)。在這種優化不可能的情況下內聯仍然可以更快,因爲它消除了函數調用開銷,並且可以允許更好的寄存器分配,並且使代碼更有可能處於緩存中。但是內聯可能很糟糕,因爲它會導致代碼膨脹和緩存污染,使得代碼不太可能在緩存中。
如果你不知道在編譯時你想從b調用哪個函數,你需要間接尋址。因此,你將有foo_1和foo_2,並且你將傳遞給b的指針,它將調用該指針所指向的函數,而不知道它是哪一個。這有一個表現懲罰,但有時是必要的。
double foo_1(int a) { return a * 3.1415926; }
double foo_2(int a) { return a * 2.81; }
void b(double (*foo)(int)) { printf("%f\n", foo(10)); }
int main(int argc, char *argv[])
{
if (argc < 2) return;
b(argv[1][0]-48 ? &foo_1 : &foo_2);
return 0;
}
C++有一個功能,您可以在告訴編譯器從相同的源代碼生成兩個版本的函數B的:一個總是調用FOO_1,另一個總是調用FOO_2。然後,foo_1和foo_2可以在兩個呼叫站點內聯,而不是選擇將指針傳遞給foo_1或foo_2到b,您將需要選擇調用b_with_foo_1或b_with_foo_2。
爲什麼標記爲「C」? – 2012-04-16 02:18:18
您在這裏沒有任何類,從來沒有想過在類中使用指針 – 2012-04-16 02:58:25
談論@BenVoigt的說法:將問題的標題改爲「使用函數指針與內聯的效率損失」 ?這就是問題所在((或者其實不是)?) – jogojapan 2012-04-16 03:03:26