简体   繁体   English

在 map 中存储指向成员 function 的指针

[英]Store pointers to member function in the map

I'd like to map string to an instance member functions, and store each mapping in the map.我想将 map 字符串转换为实例成员函数,并将每个映射存储在 map 中。

What is the clean way of doing something like that?做这样的事情的干净方法是什么?

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;      
      }
 }  

let me know if you see a problem with this approach and what are common idioms for that?如果您发现这种方法有问题,请告诉我,常见的成语是什么?

Perhaps, I should use if-else-if statement chain, given that I have a limited number of member functions, instead of a confusing map of func pointers也许,我应该使用 if-else-if 语句链,因为我的成员函数数量有限,而不是混乱的函数指针 map

BTW, I found some of the useful info here in the c++-faq-lite顺便说一句,我在c++-faq-lite中找到了一些有用的信息

Looks fine to me, but for the fact that descrToFuncMap needs to be declared static if you intend to initialise it from inside the static function Initialize() .对我来说看起来不错,但是如果您打算从 static ZC1C425268E68385D1AB5074C17A94F1 Initialize()内部初始化,则需要声明descrToFuncMap static

If you want to make sure that Initialize() gets called, and gets called just once, you can use the Singleton pattern.如果你想确保Initialize()被调用,并且只被调用一次,你可以使用 Singleton 模式。 Basically, if you aren't doing multithreading, that just means wrapping descrToFuncMap inside its own class (called say FuncMap ) with a private constructor that calls Initialize() .基本上,如果您不进行多线程处理,那仅意味着使用调用Initialize()的私有构造函数将descrToFuncMap包装在其自己的 class (称为FuncMap )中。 Then you add a static local variable of type FuncMap to Processor::Process() -- because the variable is static , it persists and is only initialised once.然后,将 FuncMap 类型的static局部变量FuncMapProcessor::Process() ——因为该变量是static ,它会持续存在并且只初始化一次。

Example code (I now realise that friend isn't really necessary here):示例代码(我现在意识到这个friend在这里并不是真正需要的):

class Processor {
private:
    typedef double (MyClass::*MemFuncGetter)();

    class FuncMap {
    public:
        FuncMap() {
            descrToFuncMap["X"]=&MyClass::GetX;
            descrToFuncMap["SomethingElse"]=&MyClass::GetSomethingElse;
            descrToFuncMap["RR"]=&MyClass::GetRR;
            descrToFuncMap["T"]=&MyClass::GetT;
        }

        // Of course you could encapsulate this, but its hardly worth
        // the bother since the whole class is private anyway.
        map<std::string, MemFuncGetter> descrToFuncMap;
    };

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

void Processor::Process(MyClass ms, const std::string& key) {
    static FuncMap fm;      // Only gets initialised on first call
    map<std::string, Getter>::iterator found=fm.descrToFuncMap.find(key);
    if(found!=fm.descrToFuncMap.end()) {
        MemFuncGetter memFunc=found->second;
        double dResult=(ms).*memFunc();    
        std::cout<<"Command="<<key<<", and result="<<result<<std::end;      
    }
}

This is not the "true" Singleton pattern as different functions could create their own, separate instances of FuncMap , but it's enough for what you need.这不是“真正的” Singleton 模式,因为不同的函数可以创建自己的、单独的FuncMap实例,但这足以满足您的需要。 For "true" Singleton, you would declare FuncMap 's constructor private and add a static method, say getInstance() , which defined the one-and-only instance as a static variable and returned a reference to that.对于“真”Singleton,您可以将FuncMap的构造函数声明为私有并添加一个 static 方法,例如getInstance() ,它将唯一的实例定义为static返回的变量的引用。 Processor::Process() would then use this with Processor::Process()然后将其与

FuncMap& fm = FuncMap::getInstance();

I'd change我会改变

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

to

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

Don't see any bad side effect for now.暂时看不到任何不良的副作用。 Probably with boost::function as a map value it will be easier in the future.可能使用 boost::function 作为 map 值,将来会更容易。

Avoid using 'virtual' if you are using maps of function pointers.如果您使用 function 指针的映射,请避免使用“虚拟”。 In this context, using 'virtual' keyword will not help much.在这种情况下,使用 'virtual' 关键字不会有太大帮助。 For example例如

descrToFuncMap["X"]=&MyClass::GetX;

will always call ' MyClass::GetX ' function even if GetX is overridden by the derived class of MyClass.将始终调用“ MyClass::GetX ”function,即使GetX被 MyClass 的派生 class 覆盖。

Usually you won't have large number of functions in class, rather than using map you can create simple struct array and use a for loop.通常您不会在 class 中拥有大量函数,而不是使用 map 您可以创建简单的结构数组并使用 for 循环。 If the number of functions are small, there won't be any big performance difference in map and array.如果函数数量很少,map 和阵列不会有太大的性能差异。 Something similar to code below will work类似于下面代码的东西会起作用

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;
        }
    }     
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM