将回调函数传递给 std::map 的最佳方法是什么?
What is the best way to pass callback function to std::map?
我正在尝试处理以下代码,但程序崩溃了:
#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef void (*callBackMethod)(string);
class CTest
{
private:
map<string, callBackMethod> mapMethod;
void testMethod(string msg)
{
cout << msg << endl;
}
public:
CTest()
{
addFunction("AA", (callBackMethod) &CTest::testMethod);
}
void addFunction(string funName, callBackMethod methodName)
{
mapMethod[funName] = methodName;
}
callBackMethod getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
return 0;
}
我有一个要求,我需要将私有方法传递给地图。程序编译时出现警告:
converting from 'void (CTest::*)(std::__cxx11::string) {aka void (CTest::*)(std::__cxx11::basic_string<char>)}' to 'callBackMethod {aka void (*)(std::__cxx11::basic_string<char>)}'
当我执行它时,它崩溃了。
当我将回调方法移到 class 之外时,它起作用了。我的要求是使程序流成为这样(隐藏需要添加到地图的外部调用的方法)。
期待您的评论。
由于您想使用成员变量,因此您需要在 typedef
:
中以不同方式指定签名
在 C++ Builder 中可以完成以下操作:
typedef void(__closure *callBackMethod)(string);
如果你这样做,我建议你保留一个指向成员所属对象的智能指针,这样你就可以在调用函数之前检查对象是否仍然有效,否则会导致应用程序崩溃。
__closure
关键字是一个 C++ Builder 扩展,用于解决使用完全限定成员名称的要求 source
为了处理全局函数和成员函数,我们有以下内容:
typedef void(__closure *callBackMethodMember)(string);
typedef void (*callBackMethodGlobal)(string);
/* And then on 2 overloaded functions */
void addFunction(string funName, callBackMethodMember methodName) {}
void addFunction(string funName, callBackMethodGlobal methodName) {}
如果需要同时指向CTest
成员函数和自由函数,那么可以使用std::function<void(std::string)>
.
#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;
using callBackFunction = std::function<void(string)>;
void testFunction(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
class CTest
{
private:
map<string, callBackFunction> mapMethod;
void testMethod(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
public:
CTest()
{
addFreeFunction("AA", testFunction);
addMemberFunction("BB", &CTest::testMethod);
}
void addMemberFunction(string funName, void(CTest::*methodName)(string))
{
using std::placeholders::_1;
mapMethod[funName] = std::bind(methodName, this, _1);
}
void addFreeFunction(string funName, void(*methodName)(string))
{
mapMethod[funName] = methodName;
}
callBackFunction getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
test.runFunction("BB");
return 0;
}
请注意,CTest
必须根据传递的函数类型以不同的方式将元素插入到映射中,因为对于成员函数,您必须提供要为其调用的对象,this
在这个例子中。这是通过使用 std::bind
.
实现的
我正在尝试处理以下代码,但程序崩溃了:
#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef void (*callBackMethod)(string);
class CTest
{
private:
map<string, callBackMethod> mapMethod;
void testMethod(string msg)
{
cout << msg << endl;
}
public:
CTest()
{
addFunction("AA", (callBackMethod) &CTest::testMethod);
}
void addFunction(string funName, callBackMethod methodName)
{
mapMethod[funName] = methodName;
}
callBackMethod getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
return 0;
}
我有一个要求,我需要将私有方法传递给地图。程序编译时出现警告:
converting from 'void (CTest::*)(std::__cxx11::string) {aka void (CTest::*)(std::__cxx11::basic_string<char>)}' to 'callBackMethod {aka void (*)(std::__cxx11::basic_string<char>)}'
当我执行它时,它崩溃了。
当我将回调方法移到 class 之外时,它起作用了。我的要求是使程序流成为这样(隐藏需要添加到地图的外部调用的方法)。
期待您的评论。
由于您想使用成员变量,因此您需要在 typedef
:
在 C++ Builder 中可以完成以下操作:
typedef void(__closure *callBackMethod)(string);
如果你这样做,我建议你保留一个指向成员所属对象的智能指针,这样你就可以在调用函数之前检查对象是否仍然有效,否则会导致应用程序崩溃。
__closure
关键字是一个 C++ Builder 扩展,用于解决使用完全限定成员名称的要求 source
为了处理全局函数和成员函数,我们有以下内容:
typedef void(__closure *callBackMethodMember)(string);
typedef void (*callBackMethodGlobal)(string);
/* And then on 2 overloaded functions */
void addFunction(string funName, callBackMethodMember methodName) {}
void addFunction(string funName, callBackMethodGlobal methodName) {}
如果需要同时指向CTest
成员函数和自由函数,那么可以使用std::function<void(std::string)>
.
#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;
using callBackFunction = std::function<void(string)>;
void testFunction(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
class CTest
{
private:
map<string, callBackFunction> mapMethod;
void testMethod(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
public:
CTest()
{
addFreeFunction("AA", testFunction);
addMemberFunction("BB", &CTest::testMethod);
}
void addMemberFunction(string funName, void(CTest::*methodName)(string))
{
using std::placeholders::_1;
mapMethod[funName] = std::bind(methodName, this, _1);
}
void addFreeFunction(string funName, void(*methodName)(string))
{
mapMethod[funName] = methodName;
}
callBackFunction getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
test.runFunction("BB");
return 0;
}
请注意,CTest
必须根据传递的函数类型以不同的方式将元素插入到映射中,因为对于成员函数,您必须提供要为其调用的对象,this
在这个例子中。这是通过使用 std::bind
.