简体   繁体   中英

Am I using function pointers correctly?

I have a function that looks something like this in pseudocode:

std::string option = "option1" // one of n options, user supplied

for (int i = 0; i < 100000; i++) {

    if (option == "option1") {
        doFunction1a();
    } else if (option == "option2") {
        doFunction2a();
    } else if (option == "option3") {
        doFunction3a();
    }

    //  more code...

    if (option == "option1") {
        doFunction1b();
    } else if (option == "option2") {
        doFunction2b();
    } else if (option == "option3") {
        doFunction3b();
    }

}

However, I could avoid the repeated if statement inside the loop by doing something like this:

std::string option = "option1" // one of n options, user supplied

int (*doFunctiona)(int, int);
int (*doFunctionb)(int, int);

if (option == "option1") {
    doFunctiona = doFunction1a;
    doFunctionb = doFunction1b;
} else if (option == "option2") {
    doFunctiona = doFunction2a;
    doFunctionb = doFunction2b;
} else if (option == "option3") {
    doFunctiona = doFunction3a;
    doFunctionb = doFunction3b;
}

for (int i = 0; i < 100000; i++) {

    doFunctiona();

    //  more code...

    doFunctionb();

}

I realize that this will have little effect on performance (the time spend by the functions dominates the time it takes to execute the if statement).

However, In terms of "good coding practices", is this a good way to set up variable function calling? With "good" I mean: (1) easily expandable, there could easily be 20 options in the future; 2) results in readable code. I'm hoping there exists some kind of standard method for accomplishing this. If not, feel free to close as opinion based.

Just use an unordered_map and spare yourself the if-else-if-orgy:

std::unordered_map<std::string, std::vector<int (*)(int, int)>> functions;
functions.insert({ "option1", { doFunction1a, doFunction1b } });
...
const auto& vec = functions["option1"];
for(auto& f : vec) f(1, 2);

Beside using map I recommend to use std::function and lambdas which will give you more flexibility and syntax is more friendly (at least for me):

std::unordered_map<std::string, std::function<void()>> functions {
    {
        "option1", 
        [] { 
            functionA();
            functionB();
        }
    },
    {
        "option2", 
        [] { 
            functionC();
            functionD();
        }
    }
};

auto optionFuncIt = functions.find("option1");
if (optionFuncIt != functions.end()) {
     optionFuncIt->second();
} else {
     std::cerr << "Invalid option name" << std::endl;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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