2014-08-31 103 views
1

我只是打角落找尋與C.這是某種形式的「階級」我做:如何避免C中的「self」參數?

typedef struct test{ 
    int x; 
    int y; 
    int(*mul)(test *); 

} mult; 

int testMul(test *t){ 
    return t->x * t->y; 
} 

mult newTest(int x_in, int y_in){ 
    mult tmp; 
    tmp.x = x_in; 
    tmp.y = y_in; 
    tmp.mul = &testMul; 
    return tmp; 
} 

如果我想使用mul()「方法」,我不喜歡這樣寫道:

mult a = newTest(2,6); 
a.mul(&a); //12 

有沒有一些巧妙的方法來避免&a參數,同時仍然可以訪問mul()函數中的struct-Params?

+0

您可能會製作一個宏來幫助您。 – 2014-08-31 20:30:25

+4

不,在您的代碼中,您應該*做任何事情都無法做到這一點。另外,如果您不希望函數被替換/定製,您應該簡單地將它作爲一個外部函數,它將您的類型作爲參數,而不是嘗試複製OOP語言的語法(或僅使用C++)。在C中,通常的做法是編寫test_multiply(&a)而不是a.multiply(),其中「test」是「類」的名稱。 – 2014-08-31 20:35:54

+1

'int testMul(test * t){'typedeffed的名字是'mult',而不是'test'。 (你是否在使用C++編譯器?) – wildplasser 2014-08-31 20:38:21

回答

1

可悲的是,沒有乾淨的方式做到這一點,但你不能老是避免傳遞參考功能,因爲功能無國籍

但你可以把它像這樣使它看起來更好:

(這正好實現):

struct test { 
    int x; 
    int y; 
}; 

test_t _test_create(int const x, int const y) 
{ 
    test_t t = malloc(sizeof(* t)); 
    if (!t) return NULL; 

    t->x = x; 
    t->y = y; 
    return t; 
} 

int _test_mul(test_t t) 
{ 
    return t->x * t->y; 
} 

使用全局變量保存函數指針:

(這走遍全球):

typedef struct test *test_t; 

struct { 
    test_t (*create)(int const x, int const y); 
    int (*mul)(test_t t); 
} test = { // <- also implementation (you don`t want to expose private function names) 
    .create = _test_create, 
    .mul = _test_mul 
}; 

您需要調用它,就像這樣:

test_t a = test.create(2, 6); 

test.mul(a); 

這樣做的好處在於你總是看到什麼a爲參考。但是由於test指針表也會消耗更多內存。

解決這個(提前警告宏)其他方式:

#define test(obj, method, args...) \ 
    (obj)->method(args) 

test_t a = newTest(2, 6); 
test(a, mul); 

但隨着指針這隻作品。你需要注意非常

+0

我喜歡你的解決方案,但你會推薦使用或者你只是通過參考? – Daveman 2014-08-31 20:58:16

+0

我會讓客戶端輸入* opaque *,並使用/傳遞引用。 (但沒有用戶知道它)。在分配時,我會使用對引用的引用(例如test.create(&test,2,6)(只需要返回值))。否則'test_t test = test.create(2,6);' – d3L 2014-08-31 21:00:25

0

我通常去宏,例如

#define MUL(a) (a).mul(&(a)) 
+0

雖然這可行,但它是一種黑客攻擊,我強烈建議不要在任何實際代碼中做。 – 2014-08-31 20:36:22

+0

但是,如果我這樣使用它,theres沒有理由將我的功能添加到結構a全部,不是嗎?如果我有兩個具有不同mul函數的結構類型,我該怎麼辦? (例如float和int) – Daveman 2014-08-31 20:47:34

+0

@MichaelAaronSafyan我完全沒有看到這件事有什麼蹊蹺。我經常發現自己需要將不同的函數附加到某個'struct'的不同實例上。對於這種宏,每個實例都是獨立的,我只需要改變它的初始化行來改變附加的功能。 – downhillFromHere 2014-08-31 20:50:00

1

的一種方法是定義一個輔助函數(類名mult和方法名mul命名):

int mult_mul(mult *x) { return x->mul(x); } 

,那麼你會:

mult a = newTest(2,6); 
mult_mul(&a)); 

這提供了多態行爲,而不必須重複對象名稱a。當然,對於其他方法,您可以爲mult_xxx()函數添加其他參數。