2012-03-20 89 views
3

所以,如果有'有趣',我決定使用指針函數在C中模擬C++成員函數。下面是一個簡單的代碼:使用指針函數來模仿C結構中的成員函數

obj.h:

#ifndef OBJ_H 
#define OBJ_H 

#include <stdlib.h> 
#include <stdio.h> 

struct Obj{ 
    struct pObjVar* pVar; 

    void (*read)(struct Obj*); 
    void (*set) (struct Obj*, int); 
}; 

struct Obj* newObj(); 
void deleteObj(struct Obj** obj); 

#endif 

obj.c:

​​

main.c中:

#include "obj.h" 

int main(void) 
{ 
    struct Obj* a = newObj(); 
    a->set(a, 10); 
    a->read(a); 
    deleteObj(&a); 

    return 0; 
} 

輸出:

>./a.out 
Value = 10  

然而,在這樣做的時候,我想我必須通過明確地將它傳遞給我的成員函數來仿效隱式指針this的作用。我猜,這工作正常,除了它使整個事情看起來很奇怪!

如果我想傳遞對象,爲什麼要實現函數作爲成員函數?我發現它的唯一答案可能是你想要一個統一的界面,但各種實現? (類似C++虛擬函數?)

什麼是(如果有)某些其他原因來模仿成員函數?此外,有沒有辦法避免通過顯式的this_指針呢?

編輯:傳遞對象時原始代碼存在問題。我錯誤地將&a用於read/set函數。如果您想要在內部將指針設置爲NULL,則只需要deleteObj

+1

您正在傳遞指向函數的_address_,即'Obj **'。跳過函數調用中的&&。 – 2012-03-20 10:26:04

+0

@JoachimPileborg:你是對的。請參閱我的編輯 – GradGuy 2012-03-20 10:38:05

+0

我曾經不得不使用類似的方法維護一個遺留項目,具有複雜的繼承層次,並且使用不透明的typedef'ed int值而不是指向結構的指針。不用說,調試/維護是一場噩夢! – SirDarius 2012-03-20 10:44:21

回答

3

只是寫的另一種方式:

#define member(FUNC, ...) FUNC(this_, ## __VA_ARGS__) 
int reader(struct Obj *_this) { 
    member(read, a, b, c); 
    member(getch); 
    return 0; 
} 

這可用於實現接口,繼承和許多C++功能,它實現了這樣的帶類的C倍。在Linux內核中,文件操作是這樣實現的。文件結構存儲指向函數的指針,以便每個文件系統可以存儲它自己的系統調用處理程序,這些處理程序在結構中的數據上運行。

1

不,在C中無法自動執行此操作。標準預處理器無法勝任轉換。

現在還有一種方法可以找到它被稱爲a->func(10)的功能。在功能裏面它只是func(10)。當Bjarne Stroustrup開始設計C++時,他爲此編寫了一個特殊的預處理器/編譯器Cfront

實際上,C++並不真正存儲指向(非虛擬)函數的指針。它只是在編譯代碼時將a->set(10)轉換爲類似struct_Obj_set(a, 10)的東西。