我需要使用std::map
对实现<std::string, fn_ptr>
。函数指针是指向拥有映射的同一类的方法的指针。我们的想法是直接访问方法,而不是实现交换机或等效方法。
(我使用std::string
作为地图的键)
我对C ++很陌生,所以有人会发布一些伪代码或链接,讨论用函数指针实现一个映射吗? (指向拥有地图的同一个类所拥有的方法的指针)
如果您认为我的问题有更好的方法,也欢迎提出建议。
答案 0 :(得分:28)
这是我能想到的最简单的事情。注意没有错误检查,并且地图可能有用地变为静态。
#include <map>
#include <iostream>
#include <string>
using namespace std;
struct A {
typedef int (A::*MFP)(int);
std::map <string, MFP> fmap;
int f( int x ) { return x + 1; }
int g( int x ) { return x + 2; }
A() {
fmap.insert( std::make_pair( "f", &A::f ));
fmap.insert( std::make_pair( "g", &A::g ));
}
int Call( const string & s, int x ) {
MFP fp = fmap[s];
return (this->*fp)(x);
}
};
int main() {
A a;
cout << a.Call( "f", 0 ) << endl;
cout << a.Call( "g", 0 ) << endl;
}
答案 1 :(得分:3)
模板实现可能如下所示:
class Factory {
public:
enum which {
foo, bar, baz
};
template<which w>
A* newA(...);
...
};
template<Factory::which w>
A* Factory::newA(...) {
/* default implementation */
throw invalid_argument();
}
template<>
A* Factory::newA<Factory::foo>(...) {
/* specialization for a 'foo' style A */
...
}
....
这要求在编译时确定用于确定调用哪个newA
的值。您可以使用const char *
作为模板参数,但不保证可以在所有编译器上使用。
另一个选择是创建帮助工厂,每个工厂创建方法一个,并将它们存储在地图中。这不是存储方法指针的一个巨大优势,但是它允许您定义默认创建方法并简化从地图中获取内容(不需要检查密钥是否存在,因为您将获得默认工厂)。在缺点方面,每个未知密钥的条目将被添加到地图中。
此外,如果您使用enum
而不是字符串作为密钥类型,则无需担心检查映射中是否存在密钥。虽然有人可能会将无效的enum
密钥传递给newA
,但他们必须明确地抛出参数,这意味着他们不会意外地执行此操作。我很难想象有人会故意在newA
中造成崩溃;潜在的场景涉及安全性,但应用程序员可能会在不使用您的类的情况下使应用程序崩溃。
答案 2 :(得分:1)
另一种选择是使用委托作为函数指针的反对者。 This委托实现非常快,支持多态性,并且可以很好地与stl容器配合使用。 你可以有类似的东西:
class MyClass {
public:
// defines
typedef fastdelegate::FastDelegate2<int, int, int> MyDelegate;
typedef std::map<std::string, MyDelegate> MyMap;
// populate your map of delegates
MyClass() {
_myMap["plus"] = fastdelegate::MakeDelegate(this, &Plus);
_myMap["minus"] = fastdelegate::MakeDelegate(this, &Minus);
}
bool Do(const std::string& operation, int a, int b, int& res){
MyMap::const_iterator it = _myMap.find(operation);
if (it != _myMap.end()){
res = it.second(a,b);
return true;
}
return false;
}
private:
int Plus (int a, int b) { return a+b; }
int Minus(int a, int b) { return a-b; }
MyMap _myMap;
};
答案 3 :(得分:1)
从C ++ 14开始,我们可以使用泛型lambda轻松摆脱成员方法的指针 它遵循由通用lambda函数构成的前向函数的最小工作示例:
File fileDir = new File(getFilesDir() + "/hola.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(fileDir), "ISO-8859-1"));