C++如何通过回调方法访问成员变量

C++ How To Access Member Variables Through A CallBack Method

本文关键字:访问 成员 变量 方法 回调 何通过 C++      更新时间:2023-10-16

我使用SQLite的sqlite3_exec函数和静态回调函数来处理一些信息。我想将生成的信息打印到一个名为sqlite3_exec的类中定义的文件中。,我说的有点像这样

class MakingTheCall{
static int CallBack(void *NotUsed, int argc, char **argv, char **azColName)
{
    for(int x = 0; x < argc; x++)
        File << argv[x];
    File<<"n";
} 
private:
   static ofstream File;
   void call(){
       sqlite3_exec(database, query, callback, 0, &zErrMsg);
   }
};

我真正想要的是静态函数使用特定于实例的FILE。因此,MakingTheCall的哪个实例进行调用都会传递其唯一的非静态FILE对象。

但由于CallBack是静态的,必须(我认为)是回调,所以它无法访问类的this指针。所以我的想法是,如果函数中有friend函数,那么它可以到达this指针。这是假设我正确理解这篇文章。

我觉得我的思路有缺陷。对于函数将使用哪个this,感觉可能仍然存在歧义。

作为本讨论的第2部分,有没有一个例子可以说明静态朋友方法会在哪里使用?它们并不是我在第一条评论中读到的互斥修饰符,所以你什么时候会同时使用它们呢?

我是SQLite和CallBacks的新手,所以我很可能错过了一些可以让我的生活变得轻松的东西。就像void*指针一样,我该如何使用它?这感觉就像是我想做什么的关键。

提前谢谢。

sqlite3_exec()调用中传递对象指针:

sqlite3_exec(database, query, callback, (void*) this, &zErrMsg);

你会在回调的NotUsed参数中得到它:

static int CallBack(void *NotUsed, int argc, char **argv, char **azColName)
{
    MakingTheCall* obj = (MakingTheCall*) NotUsed;
    // whatever....
}

严格来说,Callback()函数应该是extern "C"自由函数,而不是静态成员。

如果使用C++11支持进行编译,则可以使用匿名函数(lambda表达式)。示例:

class MakingTheCall
{
private:
   ofstream File;
   void call(){
       sqlite3_exec(database, query,
           [&] (void *NotUsed, int argc, char **argv, char **azColName) -> int
           {
               for(int x = 0; x < argc; x++)
               File << argv[x];
               File<<"n";
           },
           0, &zErrMsg);
   }
};

[&]意味着,call中可用的所有变量都是通过引用捕获的,包括this指针。有关详细信息,请参阅此处(维基百科)。

通常,这是通过在注册回调时将指向对象的指针作为闭包参数的一部分来实现的。在sqlite3_exec的情况下,API如下:

int sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);

因此,我会将指向对象的指针作为参数4传入。回调函数仍然是静态的,但它应该做的第一件事是将第一个参数强制转换为指向感兴趣对象的类的指针。然后,您可以调用所需的函数,该函数将允许您写入特定于已传递实例的File。所以你的代码可能看起来像这样:

static int CallBack(void *closure, int argc, char **argv, char **azColName)
{
    MakingTheCall* obj = static_cast<MakingTheCall*>(closure);
    obj->WriteToTheFile(argc, argv);
    return 0; // Have to return something.
}
int WriteToTheFile(int argc, char **argv)
{
    for(int x = 0; x < argc; x++)
        File << argv[x];
    File<<"n";
}