首页 > 解决方案 > 将函数指针传递给另一个类的方法

问题描述

我正在做我的第一个 C++ 项目。我有 2 个类:1 个用于与 sqlite db 的交互,另一个用于 qt 主窗口。我主要创建一个新窗口。在窗口构造函数中,我想加载数据库的内容并将其显示在 QtWidget 中。

因此,如果我理解得很好,将为 sqlite3_exec 返回的每一行调用 sqlite 回调函数。我在数据库类中创建了一个 select_all 函数,该函数将回调函数作为参数,因此我将能够使用相同的 sql 函数以不同的方式显示/使用数据。

#include <cstdio>
#include <iostream>
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
#include <qmainwindow.h>
#include <qstandarditemmodel.h>
#include <sqlite3.h>
#include <string>

using namespace std;

class Database {
public:
  sqlite3* db;
  Database() {db = create_or_open_database();}
  
  sqlite3* create_or_open_database()
  {
    sqlite3 *db = NULL;
    const char *query;
    int ret = 0;
    char *errorMsg = 0;

    ret = sqlite3_open("expense.db", &db);
    query = "CREATE TABLE IF NOT EXISTS EXPENSES(NAME TEXT KEY NOT NULL, AMOUNT INT NOT NULL, TAG TEXT, SUBTAG TEXT, DATE CHAR(10) NOT NULL);";
    ret = sqlite3_exec(db, query, callback, 0, &errorMsg);
    return db;
  }
  
  void select_all(int (*f)(void*, int, char**, char**)){
    int ret = 0;
    char *errorMsg = 0;
    
    const char *query = "SELECT * FROM EXPENSES";
    ret = sqlite3_exec(db, query, (*f), 0, &errorMsg);
  }
};


class MainWindow
{
public:
  QWidget window;
  Database expenses;
  QTreeView *navigateView = new QTreeView;
  QTreeView *expensesList = new QTreeView;
  QPushButton *newButton = new QPushButton;
  QVBoxLayout *mainVLayout = new QVBoxLayout;
  QHBoxLayout *listHLayout = new QHBoxLayout;
  QStandardItemModel *expensesModel = new QStandardItemModel;
  
  MainWindow()
  {
    QSizePolicy navigateSize(QSizePolicy::Preferred, QSizePolicy::Preferred);
    QSizePolicy expenseListSize(QSizePolicy::Preferred, QSizePolicy::Preferred);
    navigateSize.setHorizontalStretch(1);
    navigateView->setSizePolicy(navigateSize);
    expenseListSize.setHorizontalStretch(2);
    expensesList->setSizePolicy(expenseListSize);
    newButton->setText("New");
    listHLayout->addWidget(navigateView);
    listHLayout->addWidget(expensesList);
    mainVLayout->addLayout(listHLayout);
    mainVLayout->addWidget(newButton);
    window.setLayout(mainVLayout);

    // int (MainWindow::*foo)(void*, int, char**, char**) = &MainWindow::display_expenses_in_list;
    // expenses.select_all(foo);
    expenses.select_all(this->display_expenses_in_list);
  }

  int display_expenses_in_list(void *NotUsed, int argc, char **argv, char **azColName)
  {
    QStringList list = {"Name", "Amount (€)", "Tag", "Subtag", "Date"};
    this->expensesModel->setVerticalHeaderLabels(list);
    // here I'll create items and add them to the QTreeView
    return 0;
  }
};    
int main(int argc, char* argv[])
{
  QApplication app(argc, argv);
  MainWindow ui;
  ui.window.show();
 
  return app.exec(); 
}

有了这段代码,我得到reference to a non-static member function must be called [bound_member_function]

如果用谷歌搜索它并尝试,我猜,创建一个指向回调函数的函数指针 foo (当前注释的行)。我明白了:Cannot initialize a parameter of type 'int (*)(void *, int, char **, char **)' with an lvalue of type 'int (MainWindow::*)(void *, int, char **, char **)' [init_conversion_failed]

如果我设为display_expenses_in_list静态,则无法编辑费用模型...

标签: c++sqlitepointers

解决方案


这里的关键void*sqlite3_exec. 你现在通过了0,但你需要通过this

你现在可以制作display_expenses_in_list静态的了。NotUsed然后使用该参数。您只需要将其转换回MainWindow*并使用它而不是this.


推荐阅读