将类成员函数作为参数从同一类的另一个成员函数传递
pass class member function as argument from another member function of the same class
我提供了我正在处理的问题的一个更简单的版本。
我有一个类Entity
,它有一个user
对象的map
。为了简单起见,我只添加了一个元素(name
)。我已经围绕userMap
对象实现了getter
和setter
。
wrapper
函数对我来说是必需的,用于处理多线程情况下的关键情况。(此处未显示)。我通过一些SO线程以某种方式实现了一个工作示例。
但正如您所看到的,当在procedure
函数中使用wrapper
函数时,我必须在三个地方编写(id,arg)
元组参数。是否有一种方法可以通过为函数参数设置某种占位符来实现相同的功能,以便调用包装器看起来很干净,即wrapper(1,static_cast<void*>(&name),function_ptr)
。
#include <iostream>
#include <functional>
#include <map>
using namespace std;
class Entity {
public:
struct user {
int id;
string name;
};
map<int,user> userMap;
void getUserName(int id,void * arg);
void setUserName(int id,void * arg);
void procedure();
void wrapper(int id,void*,std::function<void(int,void*)>);
};
void Entity::getUserName(int id,void *arg) {
auto iter = userMap.find(id);
if(iter != userMap.end()) {
*static_cast<string*>(arg) = iter->second.name;
}
}
void Entity::setUserName(int id,void *arg) {
auto iter = userMap.find(id);
if(iter != userMap.end()) {
iter->second.name = *static_cast<string*>(arg);
}
}
void Entity::wrapper(int id,void *arg,std::function<void(int,void*)> func) {
cout <<"nSome Other critical task based on id"<< endl;
// then call the callback
func(id,arg);
}
void Entity::procedure() {
cout <<"Procedure starts"<<endl;
user u = {};
u.id = 1;
u.name = "abc";
this->userMap[1] = u;
string name;
wrapper(1,static_cast<void*>(&name),[this](int id,void*arg){
getUserName(id,arg);
});
cout <<"name :"<< name << endl;
cout <<"nSome processing..."<<endl;
name = "def";
wrapper(1,static_cast<void*>(&name),[this](int id,void*arg){
setUserName(id,arg);
});
cout <<"nSome more processing..."<<endl;
wrapper(1,static_cast<void*>(&name),[this](int id,void*arg){
getUserName(id,arg);
});
cout <<"name :"<< name << endl;
cout <<"Procedure ends"<<endl;
}
int main() {
Entity E;
E.procedure();
}
输出:
Some Other critical task based on id
name :abc
Some processing...
Some Other critical task based on id
Some more processing...
Some Other critical task based on id
name :def
Procedure ends
谢谢!
我将从一个直接的答案开始,但请继续阅读下面的警告。
您尝试执行的操作的一个更简单的语法是将第三个参数的类型更改为wrapper()
。不要将成员函数转换为非成员函数,只需将成员函数作为参数即可。
void wrapper(int id, void* arg, void (Entity::* func)(int,void*))
{
cout <<"nSome Other critical task based on id"<< endl;
(this->*func)(id, arg);
}
然后你的电话会变得更简单:
wrapper(1, static_cast<void*>(&name), &Entity::getUserName);
wrapper(1, static_cast<void*>(&name), &Entity::setUserName);
但是这真的是你想要采取的方法吗?你依赖于人们记住调用包装器,而不是直接调用其他成员函数。如果你在某个时候忘记使用包装器,你能根据症状找到原因吗?你想试试吗?
一种更稳健的方法是将关键任务放在自己的函数中,然后让getter和setter调用它。更像:
void criticalStuff(int id)
{
cout <<"Some critical task based on idn";
}
void Entity::getUserName(int id, string & arg)
{
criticalStuff(id); // Critical stuff first.
auto iter = userMap.find(id);
if(iter != userMap.end()) {
arg = iter->second.name;
}
}
void Entity::setUserName(int id, const string & arg)
{
criticalStuff(id); // Critical stuff first.
auto iter = userMap.find(id);
if(iter != userMap.end()) {
iter->second.name = arg;
}
}
任何添加新字段的人在编写新的getter和setter时都必须记住关键内容,但更常见的情况(调用这些函数)会自动处理关键内容。此外,您还可以恢复参数的类型检查,因为似乎不再有理由将内容强制转换为void *
。
在我看来,强迫使用lambda
会给自己带来问题,我知道它们很有趣,但通常用处不大。一般来说,保持简单愚蠢(KISS),在您的情况下,只需将函数划分为两个单独的函数。
class Entity {
public:
...
void getUserName(int id,void * arg);
void setUserName(int id,void * arg);
void procedure();
void criticalTask(int id); // critical task, based on id
};
void Entity::getUserName(int id,void *arg) {...}
void Entity::setUserName(int id,void *arg) {...}
void Entity::criticalTask(int id) {
cout <<"nSome Other critical task based on id"<< endl;
}
void Entity::procedure() {
cout <<"Procedure starts"<<endl;
...
criticalTask(id);
getUserName(id, &name);
...
}
int main() {
Entity E;
E.procedure();
}
- 如何使用指针传递给函数的数组中对象的函数成员
- c++构造函数成员初始化:传递参数
- 创建 std::函数,它返回具有函数成员值的变量.分段错误
- 如何在C++通过公共函数访问私有函数成员?
- 解释了构造函数成员初始化列表
- 调用std::函数成员时内存损坏
- 是否可以为模板类的模板函数成员设置别名?
- 捕获 lambda 函数C++成员变量
- 构造函数成员初始值设定项跨成员列出,安全吗?
- 获取与在模板参数中传递的函数成员类型相同的类
- 如何从公共函数成员访问地图私有成员
- C 构造函数成员分配优化
- 使用命名空间进行函数成员定义
- 函数成员作为 CUDA 内核的参数
- 模板基类函数成员的别名
- 函数成员中用于void和继承的enable_if
- 头文件中是否定义了一个很长的Class函数成员
- 类内/构造函数成员初始化
- 使用指向部分专用函数成员的指针自动填充向量
- 指向函数成员的指针