2

If I have multiple functions that have a similar name (ie fct1, fct2, fct3...), and I'm calling them from a menu that takes the function number in parameter, is there a way to call them without making a switch with every function?

I'm thinking of something similar to this: fct[c](); //c is entered by the user, which of course doesn't work.

MrRoy
  • 1,145
  • 10
  • 9

4 Answers4

5

Insert them all to map... key is the std::string which is the function name value is a function pointer.

Once you initialize the map you can use map look up to find and execute the function and avoid a switch statement

typedef void (*Foo)(void);

std::map< std::string , Foo> FunctionMap;
//Change key type to int if numbers are needed

void PrintA()
{
    std::cout << "PrintA" << std::endl;
}

void PrintB()
{
    std::cout << "PrintA" << std::endl;
}

void ExecuteFunction( const std::string& funcName )
{
    std::map< std::string , Foo>::const_iterator iter = FunctionMap.find(funcName);
    if ( iter != FunctionMap.end() )
    {
        Foo f = iter->second;
        f();
    }
}

int main()
{

    FunctionMap["PrintA"] = PrintA;
    FunctionMap["PrintB"] = PrintB;

    ExecuteFunction("PrintA");

    return 0;
}
parapura rajkumar
  • 24,045
  • 1
  • 55
  • 85
  • Or you could just use a `std::vector` and index them the way you described in your question. This would be a better solution if you have lots of functions you could call. – Michael Price Nov 03 '11 at 02:34
  • On the other hand, the `map` approach is amenable to simplification using a preprocessor macro a la `#define MAPFUNCTION(map, name) map[#name] = name`... – Kerrek SB Nov 03 '11 at 03:27
1

You could pre-declare a list of function pointers. Thusly:

void Func1() { std::cout << "Func1" << std::endl; }
void Func2() { std::cout << "Func2" << std::endl; }
void Func3() { std::cout << "Func3" << std::endl; }

void (*funcList[])() = {Func1, Func2, Func3};

int main()
{
    funcList[0]();
    funcList[1]();
    funcList[2]();  
} 
Func1
Func2
Func3
Press any key to continue . . .

Edit: an example of initializing the array at runtime - it's like any other array of values, it just looks funny when declared.

void (*funcList[3])() = {};

void InitFuncList()
{
    funcList[0] = Func1;
    funcList[1] = Func2;
    funcList[2] = Func3;
}
JoeFish
  • 3,009
  • 1
  • 18
  • 23
  • I am trying to implement this, but I am not sure how to do it with a header file. The functions are declared in my header file, and defined in a function.cpp file. The void `(*funcList[])() = {Func1, Func2, Func3{;` goes where? – MrRoy Nov 03 '11 at 01:06
  • It doesn't matter if the functions are declared in a header file - you declare the function pointer list wherever you'll be using it. In my example it was declared as a global and statically allocated. You could also initialize it at runtime, which I'll edit into the answer above. – JoeFish Nov 03 '11 at 03:12
0

Your only option in standard C++ is to populate some kind of lookup from keys to function pointers. That could be a map using the strings as keys, or an array using the number as an index, or for that matter the switch you mentioned or a big old if/else statement comparing string values.

If you're willing to write non-portable code, look at the facilities that your system provides for looking up functions by name in an executable (dlsym, GetProcAddress or equivalent). As long as your functions are available in a symbol table, you can get at them that way. The question becomes almost equivalent to Is it possible to call a C function, given its name as a string?, except that you also have C++ name mangling to worry about.

Community
  • 1
  • 1
Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
0

If the functions all have the same signature, you can put function pointers into an array. For instance,

int option1 ()
{
}

int option2 ()
{
}

typedef int(*option)();

const option options[] = {
    &option1,
    &option2,
};
int n = sizeof(options) / sizeof(option);

int main ( int, char ** )
{
    for ( int choice = 0; (std::cin >> choice); )
    {
        if ((choice < 0) || (choice >= n)) {
            std::cout << "Invalid option." << std::endl;
        } else {
            (*options[choice])();
        }
    }
}
André Caron
  • 44,541
  • 12
  • 67
  • 125