Не определенная структура

Есть ли какая-либо польза в том, что в 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 и публичным typedef в заголовке foo.h ?

Чтобы уточнить: то, что вы спрашиваете, почему 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 но это не было точно именем, которое Vdbe бы пользователю API. Следовательно, с точки зрения пользователя, Vdbe называется sqlite3_stmt .

Таким образом, точка здесь состоит в том, чтобы различать два представления одного и того же элемента: Vdbe думает в терминах Vdbe s (независимо от того, что они есть), потому что это имя имеет смысл в контексте реализации . API говорит о sqlite3_stmt s, потому что это имя имеет смысл в контексте интерфейса .

Изменить: Как указывает Амаргош, почему бы просто не сделать это для достижения такого же эффекта?

 typedef struct Vdbe sqlite3_stmt; 

KennyTM указывает на хорошую возможную причину (пожалуйста, проголосуйте за него, я не хочу сифонировать его репутацию здесь): VDBE является лишь одним из нескольких возможных бэкендов; интерфейс использует «общий» sqlite3_stmt , и затем он применяется к тому, что использует бэкэнд для его реализации.

Он определен как это, чтобы скрыть деталь реализации sqlite3_stmt от пользователя, таким образом избегая вовлечения внутренних состояний. См. Opaque pointer .

(Это также заставляет пользователя использовать этот тип в качестве указателя, поскольку сама структура sqlite3_stmt имеет неполную реализацию.)


Редактировать: VDBE (механизм виртуальной базы данных) является всего лишь «верным» интерфейсом API SQLite3. Я считаю, что back-end изменчив, поэтому sqlite3_stmt* не обязательно является Vdbe* . Не подвергать Vdbe* в API, потому что Vdbe* деталь не должна отображаться.