2012-04-16 21 views
1

在function.h文件我已經聲明的函數爲內聯,如如何在不同的類中使用函數指針?

inline double foo(int &a) 
{ 

    return a*double value 
} 

在a.cpp文件我已經包括function.h文件並調用foo的功能在許多地方。 a.cpp文件也有一個類b的實例,我想調用b實例中的foo函數。當我在b中調用函數時,我想將函數指針傳遞給b,這樣我就可以在不包含function.h文件的情況下調用b中的foo函數。

b.cpp file 
void b_foo(a function pointer to foo function) 
{ 
    call foo 
} 

既然我已經聲明瞭函數爲內聯,我不知道,如果傳遞函數指針是有效的,而不是僅僅包括b.cpp function.h文件。

我想看看有什麼區別。

+3

爲什麼標記爲「C」? – 2012-04-16 02:18:18

+0

您在這裏沒有任何類,從來沒有想過在類中使用指針 – 2012-04-16 02:58:25

+0

談論@BenVoigt的說法:將問題的標題改爲「使用函數指針與內聯的效率損失」 ?這就是問題所在((或者其實不是)?) – jogojapan 2012-04-16 03:03:26

回答

0

無論是否會產生真正的性能差異,只有通過實現兩個版本才能找到,開啓編譯器優化並比較速度。這取決於與其他代碼相關的太多因素是可預測的。它顯然取決於你的函數實際調用的次數。

但是一般來說,內聯可能會對速度產生重大的積極影響。

爲了讓事情變得靈活,並給予你顯然使用C++(而不是C),這將是一個好主意,使用更C++ - 樣的方式處理這種情況的。請參閱this SO post瞭解各種可能性及其含義。如果您遵循問題中列出的策略之一,那麼編譯器可能會盡可能內聯,而您仍然可以獲得函數指針的靈活性。

1

試試這個:

typedef double (*foo_ptr)(int &); 

void b_foo(foo_ptr f) 
{ 
    if (f != NULL) { 
    double d = f(5); 
    } 
} 

void f() { 
    b_foo(foo); 
} 

typedef可以更容易地參考指針到函數類型。

調用它時,不需要對指針取消引用(可以,但這不是必須的)。你也不必爲參數傳遞時採取的函數的地址(同樣,你可以,如果你想)

注意

inline double foo(int &a) 
{ 
    return a*double value 
} 

是無效的,因爲它有語法錯誤。嘗試:

inline double foo(int &a) 
{ 
    return a*4.5; 
} 

你可以聲明/使用double局部變量以及代替雙字面

注意:您在實例談功能。如果你真的想調用一個成員函數,你需要:

typedef double (*B::foo_ptr)(int &); 

其中B是函數被聲明的類。然後用這種方式:

B b; 
foo_ptr f = B::foo; 
b.*f(5); 
0

點擊here「指針功能」這可能對你有幫助。我不知道,但我是新的c。我相信你需要它。

1

首先,你不用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。

+0

而不僅僅是「C++有一個功能」,至少告訴他該功能的名稱是* templates *。並說'b <&foo1>()'而不是'b_with_foo_1'。 – 2012-04-16 03:00:12

+0

我認爲這些信息太多,並且遠遠超出了他目前的需求。我相信OP在做任何* C++之前需要學習C語言。我說的是概念上重要的部分。語法很簡單。目前OP對C的語法沒有問題,但理解它的含義。如果可能的話,我會建議OP反彙編生成的代碼,以瞭解真正發生的事情。 – 2012-04-16 03:02:54