C++ 在映射中存储指向成员函数的指针

C++ 在映射中存储指向成员函数的指针,c++,design-patterns,callback,C++,Design Patterns,Callback,我想将字符串映射到一个实例成员函数,并将每个映射存储在映射中 做那样的事的干净方法是什么 class MyClass { //........ virtual double GetX(); virtual double GetSomethingElse(); virtual double GetT(); virtual double GetRR(); //........ }; class Processor { private: type

我想将字符串映射到一个实例成员函数,并将每个映射存储在映射中

做那样的事的干净方法是什么

class  MyClass
{
   //........
   virtual double GetX();
   virtual double GetSomethingElse();
   virtual double GetT();
   virtual double GetRR();
   //........
};


class Processor
{
 private:
      typedef double (MyClass::*MemFuncGetter)();
      static map<std::string, MemFuncGetter> descrToFuncMap;

 public:
        static void Initialize();
        void Process(Myclass m, string);
};

void Processor::Initialize()
{

     descrToFuncMap["X"]=&MyClass::GetX;
     descrToFuncMap["SomethingElse"]=&MyClass::GetSomethingElse;
     descrToFuncMap["RR"]=&MyClass::GetRR;
     descrToFuncMap["T"]=&MyClass::GetT;
};
void Processor::Process(MyClass ms, const std::string& key)
{
     map<std::string, Getter>::iterator found=descrToFuncMap.find(key);
     if(found!=descrToFuncMap.end())
     {
        MemFuncGetter memFunc=found->second;
        double dResult=(ms).*memFunc();    
        std::cout<<"Command="<<key<<", and result="<<result<<std::end;      
      }
 }  
class-MyClass
{
//........
虚拟双GetX();
虚拟双GetSomethingElse();
虚拟双GetT();
虚拟双GetRR();
//........
};
类处理器
{
私人:
typedef-double(MyClass::*MemFuncGetter)();
静态映射;
公众:
静态void初始化();
作废处理(Myclass m,字符串);
};
无效处理器::初始化()
{
descrToFuncMap[“X”]=&MyClass::GetX;
descrToFuncMap[“SomethingElse”]=&MyClass::GetSomethingElse;
descrToFuncMap[“RR”]=&MyClass::GetRR;
descrToFuncMap[“T”]=&MyClass::GetT;
};
无效处理器::进程(MyClass ms、const std::字符串和键)
{
找到的迭代器=descrToFuncMap.find(键);
如果(找到!=descrToFuncMap.end())
{
MemFuncGetter memFunc=found->second;
double dResult=(ms)。*memFunc();
我会改变的

void Processor::Process(MyClass ms, std::string key)


目前还没有看到任何不良副作用。可能将来使用boost::function作为映射值会更容易。

在我看来很好,但是如果您打算从静态函数
Initialize()
内部初始化它,则需要声明
descrToFuncMap

如果要确保调用
Initialize()
,并且只调用一次,可以使用Singleton模式。基本上,如果不执行多线程,这只意味着使用调用
Initialize()的私有构造函数将
descrToFuncMap
包装在自己的类(称为say
FuncMap
)中
。然后将类型为
FuncMap
static
局部变量添加到
Processor::Process()
——因为该变量是
static
,所以它会持续存在,并且只初始化一次

示例代码(我现在意识到,
friend
在这里并不是必需的):


如果您正在使用函数指针的映射,请避免使用“virtual”。在这种情况下,使用“virtual”关键字不会有多大帮助。例如

descrToFuncMap["X"]=&MyClass::GetX;
将始终调用“MyClass::GetX”函数,即使GetX被MyClass的派生类重写

通常,类中不会有大量函数,而不是使用map,您可以创建简单的结构数组并使用for循环。如果函数数量较少,map和数组的性能不会有太大差异。类似于下面代码的功能也可以使用

class  MyClass
{
   //........
   double GetX();
   double GetSomethingElse();
   double GetT();
   double GetRR();
   //........
};

typedef double (MyClass::*MemFuncGetter)();

struct FuncTable
{
    const char* m_pFuncName;
    MemFuncGetter m_pFuncPtr;
};

class Processor
{          
 public:
        void Process(Myclass& m, string);
};

static FuncTable descrToFuncMap[]
{
    { "X",  &MyClass::GetX},
    { "SomethingElse", &MyClass::GetSomethingElse },
    { "RR", &MyClass::GetRR},
    { "T", &MyClass::GetT}
};

void Processor::Process(MyClass& ms, const std::string& key)
{
    int functablesize = sizeof(descrToFuncMap)/sizeof(descrToFuncMap[0])

    for(int i=0; i< functablesize; ++i)
    {   
        if( strcmp(key.c_str(), descrToFuncMap[i].m_pFuncName)==0)
        {
            MemFuncGetter memFunc=descrToFuncMap[i].m_pFuncPtr;
            double dResult=(ms).*memFunc();    
            std::cout<<"Command="<<key<<"result="<<result<<std::end;
            break;
        }
    }     
 }
class-MyClass
{
//........
双GetX();
double GetSomethingElse();
双GetT();
双GetRR();
//........
};
typedef-double(MyClass::*MemFuncGetter)();
结构函数表
{
const char*m_pFuncName;
MemFuncGetter m_pFuncPtr;
};
类处理器
{          
公众:
作废流程(Myclass&m,字符串);
};
静态FuncTable descrToFuncMap[]
{
{“X”,&MyClass::GetX},
{“SomethingElse”,&MyClass::GetSomethingElse},
{“RR”,&MyClass::GetRR},
{“T”,&MyClass::GetT}
};
无效处理器::进程(MyClass&ms、常量std::字符串和键)
{
int functablesize=sizeof(descrToFuncMap)/sizeof(descrToFuncMap[0])
for(int i=0;i当然,我会将字符串作为常量传递给引用。我的问题可能是,如果我的成员函数数量有限,我应该使用if语句链,而不是func指针的混乱映射。是的,它是静态的(修复了它)。我喜欢私家好友类的想法。你能用一个例子来演示它吗?谢谢。实际上,我认为映射比if-else链更好。它为你提供了一个很好的钩子,以便在以后需要时存储其他元信息——只要将值类型从函数指针扩展到包含函数指针和其他任何内容的结构即可您需要的信息。我同意,看起来更好,但对于经验不足的开发人员来说更难理解。为什么它不调用重写函数呢?
FuncMap& fm = FuncMap::getInstance();
descrToFuncMap["X"]=&MyClass::GetX;
class  MyClass
{
   //........
   double GetX();
   double GetSomethingElse();
   double GetT();
   double GetRR();
   //........
};

typedef double (MyClass::*MemFuncGetter)();

struct FuncTable
{
    const char* m_pFuncName;
    MemFuncGetter m_pFuncPtr;
};

class Processor
{          
 public:
        void Process(Myclass& m, string);
};

static FuncTable descrToFuncMap[]
{
    { "X",  &MyClass::GetX},
    { "SomethingElse", &MyClass::GetSomethingElse },
    { "RR", &MyClass::GetRR},
    { "T", &MyClass::GetT}
};

void Processor::Process(MyClass& ms, const std::string& key)
{
    int functablesize = sizeof(descrToFuncMap)/sizeof(descrToFuncMap[0])

    for(int i=0; i< functablesize; ++i)
    {   
        if( strcmp(key.c_str(), descrToFuncMap[i].m_pFuncName)==0)
        {
            MemFuncGetter memFunc=descrToFuncMap[i].m_pFuncPtr;
            double dResult=(ms).*memFunc();    
            std::cout<<"Command="<<key<<"result="<<result<<std::end;
            break;
        }
    }     
 }