c++ - 将函数指针传递给另一个类的方法
问题描述
我正在做我的第一个 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
静态,则无法编辑费用模型...
解决方案
这里的关键void*
是sqlite3_exec
. 你现在通过了0
,但你需要通过this
。
你现在可以制作display_expenses_in_list
静态的了。NotUsed
然后使用该参数。您只需要将其转换回MainWindow*
并使用它而不是this
.
推荐阅读
- php - 在多维数组中搜索值
- sql - 插入时如何只允许将特定数字添加到表中的字段
- c - 为什么这个程序只打印 0?
- java - Google Cloud Vision AI 的替代品
- bash - `which` 没有在 ~/bin 中显示脚本的路径
- recursion - Vim - 将键映射到执行其他操作的函数以及该键的原始功能
- objective-c - UIAlertController 自 iOS 13 起消失
- r - 如何使用存储在 R 中另一个数据框中的列顺序从数据框中进行选择?
- python - 如何在 windows server 2012 r2 中将 laravel 作业作为服务运行并公开访问项目?
- python - 如何解释用于计算到达第 n 个楼梯的方式的代码?