简体   繁体   English

C++:如何传递通用 function 名称?

[英]C++: How to pass a generic function name?

I am building a program in c++ where the user can set a function to be called when user defined conditions are reached.我正在 c++ 中构建一个程序,用户可以在其中设置 function 以在达到用户定义的条件时调用。 I am only a little experienced with c++.我对 c++ 只有一点经验。

I know how to do this in python.我知道如何在 python 中做到这一点。 You would simply define functions and put the names of said functions into a structure (I always used a dictionary).您只需定义函数并将所述函数的名称放入结构中(我总是使用字典)。 When you go to use the function, you would make a call similar to:当您 go 使用 function 时,您将进行类似于以下的调用:

methods = { "foo" : foo, "bar" : bar } 
choice = input("foo or bar? ")
methods[choice]()

Any ideas on how to pull this off in c++ without having to hardcode everything?关于如何在 c++ 中实现这一目标而无需对所有内容进行硬编码的任何想法?

You can use a map of function pointers:您可以使用 function 指针的 map:

void foo() { }
void bar() { }

typedef void (*FunctionPtr)();
typedef std::map<std::string, FunctionPtr> FunctionMap;

FunctionMap functions;
functions.insert(std::make_pair("foo", &foo));
functions.insert(std::make_pair("bar", &bar));

std::string method = get_method_however_you_want();

FunctionMap::const_iterator it(functions.find(method));
if (it != functions.end() && it->second)
    (it->second)();

Your Python code actually translates to C++ pretty much directly:您的 Python 代码实际上几乎直接转换为 C++ :

# Python:
# Create a dictionary mapping strings to functions
methods = { "foo" : foo, "bar" : bar } 
// C++:
// create a map, mapping strings to functions (function pointers, specifically)
std::map<std::string, void(*)()> methods; 
methods["foo"] = foo;
methods["bar"] = bar;

# Python
choice = input("foo or bar? ")
// C++:
std::string choice;
std::cout << "foo or bar? ";
std::cin >> choice;

# Python:
methods[choice]()
// C++
methods[choice]();

Python's dictionary is similar to C++'s map . Python 的字典类似于 C++ 的map They're both associative containers, mapping a value from one type to a value of another (in our case, string to function).它们都是关联容器,将值从一种类型映射到另一种类型的值(在我们的例子中,是字符串到函数)。 In C++, functions aren't quite first-class citizens, so you can't store a function in a map, but you can store a pointer to a function. In C++, functions aren't quite first-class citizens, so you can't store a function in a map, but you can store a pointer to a function. Hence the map definition gets a bit hairy, because we have to specify that the value type is a "pointer to a function which takes no arguments and returns void".因此,map 定义有点复杂,因为我们必须指定值类型是“指向 function 的指针,它不接受 arguments 并返回 void”。

On a side note, it is assumed that all your functions have the same signature.附带说明一下,假设您的所有函数都具有相同的签名。 We can't store both functions that return void and functions that return an int in the same map without some additional trickery.如果没有一些额外的技巧,我们不能将返回 void 的函数和返回 int 的函数存储在同一个 map 中。

You may have a look at function pointers:你可以看看 function 指针:

http://www.newty.de/fpt/intro.html http://www.newty.de/fpt/intro.html

Another option is function objects + inheritance:另一个选项是 function 对象 + inheritance:

#include <string>
#include <iostream>
#include <conio>
#include <exception>
//---------------------------------------------------------------------------

struct Method{
    virtual ~Method(){}

    virtual
    void operator() (void)=0;
};
struct foo: public Method{
    virtual ~foo(){}

    virtual
    void operator() (void){
        std::cout << "this is foo\n";
    }
};
struct bar: public Method{
    virtual ~bar(){}

    virtual
    void operator() (void){
        std::cout << "this is bar\n";
    }
};

Method* getMethodByName(std::string methName){
    if( methName == "foo" )
        return new foo();
    else if( methName == "bar" )
        return new bar();

    throw invalid_argument("Unknown method");
}
//---------------------------------------------------------------------------

int main(int argc, char* argv[])
{
    std::string choice;

    std::cout << "foo or bar?\n";
    std::cin >> choice;

    boost::shared_ptr<Method> method = getMethodByName(choice);
    (*method)();

    getch();
    return 0;
}

Though this requires boost's smart pointer lib .虽然这需要boost 的智能指针 lib With vanilla C++:使用香草 C++:

    Method* method = getMethodByName( choice );
    try{
        (*method)();
        delete method;
    }
    catch(...){
        delete method;
    }

    getch();
    return 0;

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

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