使用包含函数名称的字符串调用函数

时间:2013-08-26 10:35:18

标签: c++

我有一个定义为

的类
class modify_field 
{
    public:
        std::string modify(std::string str)
        {
            return str;
        }

};

有没有办法将此函数名称存储在main函数的字符串中,然后调用它。 我尝试了这个,但它没有用。

int main()
{
modify_field  mf;
std::string str,str1,str2;
str = fetch_function_name(); //fetch_function_name() returns string modify
str2 = "check";
cout << str; //prints modify
str1 = str + "(" +str2 + ")";
mf.str1(); 
}

我知道这是错的。但我只想知道是否有任何方法可以使用变量调用函数名称。

6 个答案:

答案 0 :(得分:6)

这在C ++中是不可能直接实现的。 C ++是一种编译语言,因此函数和变量的名称不存在于可执行文件中 - 因此代码无法将字符串与函数名称相关联。

您可以通过使用函数指针获得类似的效果,但在您的情况下,您也尝试使用成员函数,这会使问题变得复杂一些。

我会做一个小例子,但想在我花10分钟编写代码之前得到答案。

编辑:这是一些显示我的意思的代码:

#include <algorithm>
#include <string>
#include <iostream>
#include <functional>

class modify_field 
{
public:
    std::string modify(std::string str)
        {
            return str;
        }

    std::string reverse(std::string str)
        {
            std::reverse(str.begin(), str.end());
            return str;
        }
};


typedef std::function<std::string(modify_field&, std::string)> funcptr;


funcptr fetch_function(std::string select)
{
    if (select == "forward")
        return &modify_field::modify;
    if (select == "reverse")
        return &modify_field::reverse;
    return 0;
}



int main()
{
    modify_field mf;

    std::string example = "CAT";

    funcptr fptr = fetch_function("forward");
    std::cout << "Normal: " << fptr(mf, example) << std::endl;

    fptr = fetch_function("reverse");
    std::cout << "Reverse: " << fptr(mf, example) << std::endl;
}

当然,如果您想将功能存储在map<std::string, funcptr>中,那么这是完全可能的。

答案 1 :(得分:3)

您有两种选择:

1 - 手动创建一个地图,其中包含指向所需功能的指针及其标识符作为字符串键,以便您可以执行查找,或者..

2 - 创建动态链接库/共享对象并使用名称查找来获取指针。使用extern“C”禁止标识符重整。您可能无法使用某些C ++功能,性能会稍差,具体取决于您的实际使用情况。

答案 2 :(得分:2)

对于C函数来说肯定是可能的,但是对于C ++来说真的很棘手且不可移植 - 因为不同的操作系统(甚至同一操作系统上的不同编译器)对C ++使用不同的ABI,所以实际的函数名称与你命名的有很大不同它们在你的代码中。

如果C函数正常(例如,您可以将它们声明为extern“C”),则可以将dlsym用于POSIX操作系统,将GetProcAddress用于Windows。当然,你需要将这些函数添加到动态符号表中 - 类似于ld的'-rdynamic'标志,或__declspec(dllexport)(希望这是正确的 - 如果很长时间没有使用)在Windows上。

答案 3 :(得分:1)

也许指向这个函数的指针更合适。它允许您轻松选择要调用的函数:

#include<iostream>
using namespace std;

class modify_field
{
    public:
        std::string modify_1(std::string str)
        {
            return str;
        }
        std::string modify_2(std::string str)
        {
            return str + str;
        }
};

int main()
{
    string (modify_field::* fun_ptr) (string) = &modify_field::modify_1;
    modify_field m;
    cout << (m.*fun_ptr)("test") << endl;
    fun_ptr = &modify_field::modify_2;
    cout << (m.*fun_ptr)("test") << endl;
}

答案 4 :(得分:0)

如果函数具有相同的签名,则可以创建字符串到std :: function对象的映射。在此处查看有关std :: function的更多信息:std::function

答案 5 :(得分:0)

如果您将要通过名称查找的所有函数放在随后生成DLL的源文件集中,则可以使用dlopen()dlsym()函数来查找切入点。

有关如何执行此操作的示例,请参阅计算机上dlsym()的手册页,或者您可以参考this link

这仅适用于未解码的函数(即使用C ++,您可能会遇到一些问题)。您可能必须将这些入口点定义为"extern C"以防止出现错误,或者想出一些其他机制来猜测C ++入口点的错位名称。我从来没有做过后者所以那里肯定会有一些我不知道的细微差别。

如果您使用的是Windows(不清楚您使用的是哪种操作系统),则应查找可在线hereGetProcAddress()文档。

关于这个主题的一个很好的教程,这篇文章确实讨论了如何使用C ++完成所有这些here