std ::成员函数指针的映射?

时间:2009-12-17 21:51:07

标签: c++ stl

我需要使用std::map对实现<std::string, fn_ptr>。函数指针是指向拥有映射的同一类的方法的指针。我们的想法是直接访问方法,而不是实现交换机或等效方法。

(我使用std::string作为地图的键)

我对C ++很陌生,所以有人会发布一些伪代码或链接,讨论用函数指针实现一个映射吗? (指向拥有地图的同一个类所拥有的方法的指针)

如果您认为我的问题有更好的方法,也欢迎提出建议。

4 个答案:

答案 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"));
相关问题