我有一个处理 SQL 查询的类(它使用 Qt 函数,但我认为这无关紧要)。所有写入数据的查询都具有完全相同的基本框架,如下所示:
bool Database::someSqlFunction(some variables)
{
if (! startTransaction()) {
return false;
}
QSqlQuery query(m_db);
try {
... Code using the passed variables and query ...
commitTransaction();
} catch (...) {
rollbackTransaction(query);
return false;
}
return true;
}
是否可以重新使用此代码,以便不必为每个函数定义它?我考虑过使用一个函数来调用,该函数带有指向包含不同代码的函数的指针,但是每个函数的签名都不同,因此我必须为每种情况定义一个重载的函数;我也考虑过使用预处理器来生成函数,但是不同数量和类型的参数也是同样的问题。
可以将要执行的代码块传递给另一个函数吗?还是可以通过函数模板完成?
编辑:这是如何实现的:
在标题中:
template<typename SqlFunction>
bool writeHelper(SqlFunction sqlFunction)
{
if (! startTransaction()) {
return false;
}
QSqlQuery query(m_db);
try {
sqlFunction(query);
commitTransaction();
} catch (...) {
rollbackTransaction(query);
return false;
}
return true;
}
以及使用它的示例函数:
bool Database::registerPlayers(const QString &name, int markerId)
{
return writeHelper([&](QSqlQuery &query) {
queryPrepare(query, QStringLiteral("INSERT INTO players(id, name, marker) "
"VALUES(NULL, ?, ?)"));
query.bindValue(0, name);
query.bindValue(1, markerId != 0 ? markerId : SQLITE_NULL);
queryExec(query);
});
}
编辑 2:没有模板也可以实现同样的效果:
使用 std::function
,可以简单地传递实际函数中定义的 lambda,而无需使用模板。辅助函数的实现如下所示:
bool Database::writeHelper(std::function<void(QSqlQuery &query)> sqlFunction)
{
if (! startTransaction()) {
return false;
}
QSqlQuery query(m_db);
try {
sqlFunction(query);
commitTransaction();
} catch (...) {
rollbackTransaction(query);
return false;
}
return true;
}
无论如何,使用模板方法显然更好,因为在这种情况下,编译器将在构建时生成所需的函数并可以进行优化,而他不知道使用 std::function 实际会做什么方法,因为调用发生在运行时。
最佳答案
Lambda 闭包似乎正是您所需要的。
https://en.cppreference.com/w/cpp/language/lambda
例如,通用算法与您的用例非常相似:一个常见的
不会改变的算法和一些小部分
可以在调用时自由提供。
https://en.cppreference.com/w/cpp/header/algorithm
在不知道预期的确切细节的情况下, 我在这里提供一个简单的例子:
#include <iostream>
template<typename Fnct>
void
common_part(Fnct fnct)
{
std::cout << "begin common part\n";
for(auto i=0; i<3; ++i)
{
std::cout << "iteration " << i << " of common part\n";
fnct(i);
}
std::cout << "end common part\n";
}
void
specific_function_A()
{
common_part(
[&](const auto &n)
{
std::cout << "specific part A: " << n << '\n';
});
}
void
specific_function_B(int something_else)
{
common_part(
[&](const auto &n)
{
std::cout << "specific part B: " << n+something_else << '\n';
something_else*=2;
});
}
int
main()
{
specific_function_A();
std::cout << "~~~~~~~~\n";
specific_function_B(100);
return 0;
}
即使 lambda 闭包的签名始终相同, 捕获可以被视为提供额外参数的解决方法。
关于c++ - 在 C++ 中,是否可以定义一个具有不同代码块的函数,以通过另一个函数执行和传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59125822/