2010-07-19 50 views
12

在C中有沒有定義的結構有什麼好處嗎?從未定義的結構

實施例中的SQLite源代碼:

/* struct sqlite3_stmt is never defined */ 
typedef struct sqlite3_stmt sqlite3_stmt; 

並且對象被操縱像這樣:

typedef struct Vdbe Vdbe; 
struct Vdbe { 
    /* lots of members */ 
}; 


int sqlite3_step(sqlite3_stmt *pStmt) { 
    Vdbe *v = (Vdbe*) pStmt; 
    /* do stuff with v... */ 
} 

那麼,爲什麼不直接使用通常的抽象類型,與在foo.c私下定義的實際結構來源和公衆typedeffoo.h標題?

+1

沒有很好的理由。但很多人在C中做了很多愚蠢的事情,即使在大型的着名項目中也是如此。 – 2010-07-19 09:37:23

+7

致R:你不會以那種不屑的態度走得很遠。 sqlite是一個衆所周知的成熟項目,因其質量而聞名。理查德·希普很可能知道他在做什麼。 – 2010-07-19 09:46:32

回答

9

澄清:什麼你問就是爲什麼SQLite的做,而不是做這上面:

頭文件

typedef struct sqlite3_stmt sqlite3_stmt; 

C文件:

struct sqlite3_stmt { 
    /* lots of members */ 
}; 


int sqlite3_step(sqlite3_stmt *pStmt) { 
    /* do stuff with pStmt... */ 
} 

(這是在KennyTM的答案中連接的「不透明指針」模式的規範形式)。

唯一的好我可以想到SQLite爲什麼會這樣做的原因如下:

我推測後端代碼出現在API之前,並使用名稱Vdbe - 名稱可能意味着與沿着「虛擬數據庫條目」(這裏瘋狂地猜測)。

當創建API的時候,有人意識到sqlite3_step所需的參數是Vdbe,但這並不完全是一個會向API的用戶傳達很多信息的名稱。因此,從用戶的角度來看,Vdbe被稱爲sqlite3_stmt

這裏的關鍵,那麼,兩個視圖在同一項目的區分:後端認爲在Vdbe條款(無論他們是),因爲這是有道理的實施的上下文中的名稱。 API會談到sqlite3_stmt,因爲這是一個在接口的上下文中有意義的名稱。

編輯:正如Amarghosh指出的那樣,爲什麼不僅僅是爲了達到同樣的效果?

typedef struct Vdbe sqlite3_stmt; 

KennyTM points out a good possible reason(請投他,我不想在這裏抽走他的代表):VDBE只有幾種可能的後端之一;該接口使用「通用」sqlite3_stmt,然後將其轉換爲後端用於實現它的任何內容。

+4

那麼爲什麼他們只是'typedef struct Vdbe sqlite3_stmt;' – Amarghosh 2010-07-19 09:44:31

+0

你說得對,這是我問的。我喜歡同一項目的兩種觀點。 (順便說一句,這是我對SQLite的理解,VDBE代表「虛擬數據庫引擎」) – Axel 2010-07-19 09:51:19

+0

@Amarghosh:好點... KennyTM編輯的答案提供了一個很好的可能原因(VDBE只是幾個後端之一) – 2010-07-19 10:13:51

15

它是這樣定義的,以隱藏用戶的實現細節sqlite3_stmt,從而避免內部狀態混亂。見Opaque pointer

(這也迫使用戶只能使用類型,因爲結構sqlite3_stmt本身具有完全執行的指針。)


編輯:VDBE(虛擬數據庫引擎)只是「一個」背SQLite3 API的結尾。我相信後端是可變的,因此sqlite3_stmt*不一定是Vdbe*。不要在API中公開Vdbe*,因爲後端細節不應公開。

+2

儘管如此,在不透明指針文章的示例中,定義了「struct cat_t」... 「struct sqlite3_stmt」僅用於隱藏「struct Vdbe」上的實現嗎?那麼,有沒有理由不使用'Vdbe'上的不透明指針模式? – Axel 2010-07-19 09:27:44

+0

+1「我相信後端是可以改變的」聽起來很合理! – 2010-07-19 10:15:02