2010-11-05 53 views
5

可能重複:
Can you write object oriented code in C?實驗:面向對象的C?

嗨!爲了它的樂趣,我一直在做這些最後兩天的試驗,在純C中創建一個非常簡單,非常直接的對象環境。我一直在用宏,動態鏈接,類型描述結構我已經到達以下:

string_o str = new(String, "hello world"); 
list_o list = new(List); 

List.pushf(list, str); 

printf("In the list: \"%s\"\n", 
     String.text(List.popf(list))); 

delete(list); 
delete(str); 

看起來和工作挺好,但我不能想出一個方法來僞造實例方法。我不能通過Class.function(instance),而不是沒有全局宏替換功能名稱,這破壞了封裝的目的。

再次,這是一個實驗,只是爲了挑戰和樂趣=)。你們能幫我找出一個辦法嗎?我不想使用額外的預處理,只有簡單的C和GCC宏。

編輯>忘了說 - 我不希望每個實例在其結構中包含函數指針。這會給我方法的語法好,但這意味着一個4字節的數據對象將有十幾個函數指針複製到每個實例。這有點像作弊= P哈哈

在此先感謝!

+3

是不是他們爲什麼創建cpp?:P – Tobias 2010-11-05 05:03:24

+3

將每個「類」與調用「成員函數」時執行的函數指針表相關聯? – birryree 2010-11-05 05:05:22

+0

@Tobias:_shudder_,我希望不會! [C++:通過將額外的腿釘在狗身上製成的章魚。](http://en.wikiquote.org/wiki/Programming_languages#C.2FC.2B.2B) - Steve Taylor:P – 2010-11-05 05:06:21

回答

12

C中的對象方向通常由函數指針完成。這意味着一個結構不僅包含實例的數據,還包含調用的函數。

這是在C中進行繼承和多態的最簡單的方法。舉例來說,這裏是一個面向對象的通信示例。

它只有一個方法open,但你可以看到如何不同的TCP和HTML子類。通過設置一個特定於類的函數的初始化例程,可以獲得多態性。

#include <stdio.h> 

// The top-level class. 

typedef struct _tCommClass { 
    int (*open)(struct _tCommClass *self, char *fspec); 
} tCommClass; 

// Function for the TCP class. 

static int tcpOpen (tCommClass *tcp, char *fspec) { 
    printf ("Opening TCP: %s\n", fspec); 
    return 0; 
} 
static int tcpInit (tCommClass *tcp) { 
    tcp->open = &tcpOpen; 
    return 0; 
} 

// Function for the HTML class. 

static int htmlOpen (tCommClass *html, char *fspec) { 
    printf ("Opening HTML: %s\n", fspec); 
    return 0; 
} 
static int htmlInit (tCommClass *html) { 
    html->open = &htmlOpen; 
    return 0; 
} 

// Test program. 

int main (void) { 
    int status; 
    tCommClass commTcp, commHtml; 

    // Same base class but initialized to different sub-classes. 
    tcpInit (&commTcp); 
    htmlInit (&commHtml); 

    // Called in exactly the same manner. 

    status = (commTcp.open)(&commTcp, "bigiron.box.com:5000"); 
    status = (commHtml.open)(&commHtml, "http://www.microsoft.com"); 

    return 0; 
} 

更完整的答案可以找到here

在回答您的評論:

我不想包含在每一個實例中的功能。

你可能是對的。對於單個類的每個實例而言,重複該信息是沒有必要的。

有一個簡單的方法。不是每個實例都攜帶它自己的一組函數指針,而是創建一個用於保存類的結構,然後每個實例都獲得一個指向該結構的指針。

這將節省相當多的空間,不得不做兩層間接調用函數的(最小)成本。

+0

感謝您的回答,但我忘了說,我不希望包含在每個單一實例中的函數。想象一下,如果每個列表節點或包裝的整數或其他,必須包含20個函數指針! – slezica 2010-11-05 05:25:38

+1

那麼,你可以在結構中有一個_single_指針指向一個特定於類的函數指針數組。你將不得不使用雙重間接來調用函數而不是單向間接,但它會爲你節省空間。我會將其添加到我的答案中。 – paxdiablo 2010-11-05 05:29:03

+0

對不起,我剛剛讀過!是的,我並不擔心無法達到這些功能。我可以這樣做(假設對象中的類的指針稱爲'f')object-> f-> fun(object);但它看起來醜陋地獄。我試圖宏觀我的方式object.fun(); - 雖然不知道它是否可能。 – slezica 2010-11-05 17:02:07