Чтобы уточнить: вы спрашиваете, почему 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
s (какими бы они ни были), потому что это имя имеет смысл в контексте осуществление . API говорит о sqlite3_stmt
s, потому что это имя имеет смысл в контексте интерфейса .
Редактировать: Как указывает Амаргхош, почему бы просто не сделать это для достижения того же эффекта?
typedef struct Vdbe sqlite3_stmt;
KennyTM указывает на вескую возможную причину (пожалуйста, проголосуйте за него, я не хочу отсеивать здесь его повторение): VDBE - только один из нескольких возможных бэкэндов; интерфейс использует «универсальный» sqlite3_stmt
, и затем он приводится к тому, что бэкэнд использует для его реализации.