gpt4 book ai didi

c++ - 将类成员函数作为同一类的另一个成员函数的参数传递

转载 作者:行者123 更新时间:2023-11-28 04:25:00 25 4
gpt4 key购买 nike

我提供了我正在处理的问题的更简单版本。

我有课Entity , 它有一个 mapuser目的。为简单起见,我只添加了一个元素 ( name )。我已经实现了 gettersetter userMap周围对象。

wrapper由于多线程情况,我需要函数来处理危急情况。 (此处未显示)。我通过一些 SO 线程以某种方式实现了一个工作示例。

但是如你所见,我必须写(id,arg)使用 wrapper 时三个地方的元组参数内部功能procedure功能。有没有一种方法可以通过为函数参数设置某种占位符来实现相同的功能,以便调用包装器看起来很干净,即 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);

但是这真的是您想要采用的方法吗?您依赖于人们记住调用包装器而不是直接调用其他成员函数。如果您在某个时候忘记使用 wrapper ,您是否能够根据症状追查原因?你想试试吗?

一个更稳健的方法是将关键任务放在它自己的函数中,然后让 getter 和 setter 调用它。更像是:

void criticalStuff(int id)
{
cout <<"Some critical task based on id\n";
}

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 *

关于c++ - 将类成员函数作为同一类的另一个成员函数的参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54554443/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com