Yichao Sun
Yichao Sun

Reputation: 13

How to use string to call function in a class?

I hope to use map library to call a function by a string with the function name, I've tested the following example and everything are working well.

#include <string>
#include <iostream>

using namespace std;

typedef void (*pFunc)();
map<string, pFunc> strFuncMap;

void func1()
{
    printf("this is func1!\n");
}

void buildMap()
{
    strFuncMap["func1"] = &func1;// 
}

void callFunc(const std::string& str)
{
    (*strFuncMap[str])();
}

int main()
{
    buildMap();

    callFunc("func1");
    return 0;
}

However, as I define all these things in a class, there is a compiler error occur:

#include <map>
#include <string>
#include <iostream>

using namespace std;

class theClass {
public:
    typedef void (*pFunc)();
    map<string, pFunc> strFuncMap;

    void func1()
    {
        printf("this is func1!\n");
    }

    void buildMap()
    {
        strFuncMap["func1"] = &func1;// a value of type cannot be assigned to an entity of type
    }

    void callFunc(const std::string& str)
    {
        (*strFuncMap[str])();
    }
};


int main()
{
    theClass a;
    a.buildMap();

    a.callFunc("func1");
    return 0;
}

I've tried to solve this problem for a couple of hours. Or is there any other way to use string to call function in a class? I will very appreciate if someone can help me. THANKS!!

Upvotes: 1

Views: 90

Answers (2)

user15388024
user15388024

Reputation:

Your code doesn't work because func1 is a member function and the syntax for member functions is different.

You need a map of member function pointers (offsets)

typedef void (theClass::*pFunc)();
map<string, pFunc> strFuncMap;

Then you can store the pointer with

strFuncMap["func1"] = &theClass::func1;

And you need an object to call a member function

(this->*strFuncMap[str])();

The final code:

#include <map>
#include <string>
#include <iostream>

using namespace std;

class theClass {
public:
    typedef void (theClass::*pFunc)();
    map<string, pFunc> strFuncMap;

    void func1()
    {
        printf("this is func1!\n");
    }

    void buildMap()
    {
        strFuncMap["func1"] = &theClass::func1;
    }

    void callFunc(const std::string& str)
    {
        (this->*strFuncMap[str])();
    }
};


int main()
{
    theClass a;
    a.buildMap();

    a.callFunc("func1");
    return 0;
}

Upvotes: 3

Silvio Mayolo
Silvio Mayolo

Reputation: 70277

typedef void (*pFunc)();

This declares pFunc to be the type of function pointers. That is, the type of pointers to functions which exist at the top-level. This excludes member functions, lambda functions, and functors. Consider

using pFunc = std::function<void()>

Now your type will correctly accept anything that can reasonably be interpreted as a callable object. Note that member functions still need to be wrapped in a lambda, since you're closing around this.

strFuncMap["func1"] = [this]() { this->func1(); };

Upvotes: 1

Related Questions