【发布时间】:2015-08-16 05:10:30
【问题描述】:
我对在 C++ 中处理 C 回调比较陌生。我制作了一个 sqlite 包装器 c++ 类,它只调用 sqlite3_exec()。
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
SqliteAccessor* sqlite = static_cast<SqliteAccessor*> NotUsed;
if(argc > 0) {
sqlite->set_table_exists(true);
}
return 0;
}
class SqliteAccessor{
public:
bool has_table(const string dbName, const string tblName)
{
string sql;
sql = "SELECT " + quote_string(tblName) + "FROM " + quote_string(dbName)
+ "WHERE type = 'table' AND name = " + quote_string(tblName) + ";";
char *zErrMsg = 0;
int rc = sqlite3_exec(m_db, sql.c_str(), callback, (void*) this, &zErrMsg);
if( rc != SQLITE_OK ){
printf("SQL error: %s", zErrMsg);
sqlite3_free(zErrMsg);
}
// anyway to return the result directly?
// return hasTable;
}
// can I avoid the following methods and the member variable?
void set_table_exists(bool isExist) { m_table_exist = isExist; }
bool get_table_exists() { return m_table_exist; }
private:
static bool m_table_exist;
};
int caller(){
SqliteAccessor sqlite;
// to check if table exist
if (sqlite->has_table()){
// will above work or
// I should do with an extra call to query the changed state?
}
}
现在,我很困惑调用者如何从 sqlite 包装器中获取结果。我认为,调用者不能通过简单地调用has_table() 获得结果,因为结果是由set_table_exists() 从回调返回的。那么调用者是否应该通过另一个调用来获得结果,例如打电话给sqlite->get_table_exists()?
那么这意味着对于每一个回调,我需要在SqliteAccessor类中创建一个成员变量(也必须是static),以及一对set/get_state(),这样会很麻烦。
如何设计类以使其易于被调用者使用? 不幸的是,我们的代码库不支持 c++11。
【问题讨论】:
-
即回调设置的结果。我想避免它。
-
hasTable一旦初始化为false就不会改变,所以has_table()总是返回false。如果sqlite->get_table_exists()确实存在,那是has_table()应该返回的。那么SqliteAccessor的用户除了has_table()之外什么都不需要调用。 -
我的错,我修改了它。谢谢!
-
您的问题是缺少代码。你调用了一个成员函数
set_table_exists(true),但是你没有展示它的实现。它有什么作用?如果它将成员 bool 变量设置为 true,那么是的,has_table()可以返回它的值。 -
可以吗?它是否已经由回调设置?我已经用这两个函数更新了我的代码。谢谢!
标签: c++ sqlite design-patterns callback