2010-07-19 90 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