2013-02-02 26 views
0

我有一個項目,一個情況下我必須控制它是如何工作的一些經常變化的預處理器#define秒 - 例如:生成兩個函數與C預

void myfunction(int num, mystruct* content) { 
    doSomethingTo(content); 
    //... 
    #ifdef FEATURE_X 
    feature_x(content); 
    #endif 
} 

這工作得很好,雖然它每次都必須重新編譯,所以它在「每次都必須重新編譯的東西」文件中。我想將它推入一個[靜態]庫。我確定有改變它怎麼叫(已經採摘myFunction一個函數指針),所以我想,要變成

void myfunction(int num, mystruct* content) { 
    doSomethingTo(content); 
    //... 
} 
void myfunction_featureX(int num, mystruct* content) { 
    doSomethingTo(content); 
    //... 
    feature_x(content); 
} 

我需要做的這幾個地方,所以使用一個單獨的圖書館(一個和一個沒有-D FEATURE_X)爲每個不是一個可接受的選項。我可能與複製/粘貼,但這會導致代碼重用,有一個副本,但不是另一個修復錯誤的風險。

+3

這是'代碼重用'和重構的完美反例。你應該明確地不這樣做。 – 2013-02-02 23:45:16

回答

1

函數的featureX版本調用主線函數。在你的例子中,myfunction_featureX將會調用myfunction,然後做它自己的事情。

+0

...我怎麼沒有想到這一點。如果執行順序沒有爭論的話,它將不起作用,但如果沒有關係,這個解決方案非常好。 – zebediah49

1

如果您將myfeature_x放入函數表中,它會有幫助嗎?

#include <stdio.h> 
#include <string.h> 

typedef struct { 
    int x,y; 
} mystruct; 

typedef void (*fn_ptr)(mystruct* content); 
fn_ptr vtable[10]; 
#define FEATURE_X_INDEX 0 

void feature_x(mystruct *content) 
{ 
    printf("y: %d\n", content->y); 
} 

void myfunction(int num, mystruct* content) { 
    printf("x: %d\n", content->x); 

    //... 
    if (vtable[FEATURE_X_INDEX]) { 
    vtable[FEATURE_X_INDEX](content); 
    } 
} 

int main(void) 
{ 
    bzero(vtable, sizeof(vtable)); 
    mystruct s; 
    s.x = 1; 
    s.y = 2; 
    myfunction(0, &s); 
    if (1) { 
    //Of course you'd use a more sensible condition. 
    vtable[FEATURE_X_INDEX] = feature_x; 
    } 
    myfunction(0, &s); 
    return 0; 
} 

輸出:

x: 1 
x: 1 
y: 2 

然後,所有你需要做的就是填充虛函數表NULL■如果該功能不被使用,並與函數指針,如果它是用來。您可以從任何地方執行此操作 - 例如靜態庫..或者您可以將feature_x編譯爲動態庫,在運行時加載它,並且如果加載成功填充函數表,並在動態鏈接庫爲卸載。

我認爲唯一的好處是真正讓您瞭解Jonathan Leffler的方法是,feature_x的代碼實際上並不需要鏈接到與其他代碼相同的二進制文件中。正如Jonathan Leffler所建議的那樣,如果您只需要一個運行時開關來打開或關閉該功能,則簡單的if聲明就可以應對。 (順便提一下,這裏也有一個if - 它檢查函數表的內容:))

1

當然,這是將X從編譯時問題轉換爲運行時問題的切入點:

void myfunction(int num, mystruct* content) 
{ 
    doSomethingTo(content); 
    //... 
    if (FeatureX_Enabled()) 
     feature_x(content); 
} 

FeatureX_Enabled()測試可能是一個全功能的,或者它可能被簡單地測試被定義​​在函數外適當範圍的變量 - 在該文件中的靜態變量,或外部變量。這避免了必須使用函數指針;這與現在稱爲相同的功能。更改函數指針表等同於更改單個變量 - 它涉及更改存儲在函數外部的某些值的值,以更改函數的行爲。