【问题标题】:How can I call a function from an array of functions via its index?如何通过索引从函数数组中调用函数?
【发布时间】:2022-01-18 19:37:39
【问题描述】:

我在网上找不到答案的初学者问题,可能是因为我不知道术语。

我想根据计算的索引值调用一系列过程之一。也就是说,给定一个 '1',调用 firstProc(),'2' 调用 secondProc() 等等。

所有过程都是没有参数的无效函数。

我可以用 switch/case 来实现它,但我更喜欢这样的东西:

void* action[2] {*firstProc, *secondProc};

(编译,但警告:invalid conversion from 'void (*)()' to 'void*'

然后:

action[get_index()]();

'action' 的编译器对象不能用作函数。

这一定是可能的,对吧?我已经尝试了几种变体,但我无法通过使用选定的 ('action[index]') 作为函数。

【问题讨论】:

标签: c++ arrays function


【解决方案1】:

两种等效的方法可以做你想做的事。解释在代码 sn-ps 中以 cmets 的形式给出。

方法一


#include <iostream>
void foo() 
{ 
    std::cout << "Hello";
}
void foo2() 
{ 
    std::cout << " wolrd!"; 
    
}


int main()
{
   
    void (*a)() = foo;// a is a pointer to a function that takes no parameter and also does not return anything
    
    void (*b)() = foo2;// b is a pointer to a function that takes no parameter and also does not return anything
    
    
    //create array(of size 2) that can hold pointers to functions that does not return anything and also does not take any parameter
    void (*arr[2])() = { a, b};
    
    arr[0](); // calls foo 
    
    arr[1](); //calls foo1
    
    return 0;
}

方法一可以执行here

在上面的方法1中void (*a)() = foo;意味着a是一个指向一个不带参数也不返回任何东西的函数的指针。

同样,void (*b)() = foo2; 意味着 b 是一个指向不带参数且不返回任何内容的函数的指针。

接下来,void (*arr[2])() = { a, b}; 意味着 arr 是一个数组(大小为 2),可以保存指向不返回任何内容且不带任何参数的函数的指针。

方法二


#include <iostream>
void foo() 
{ 
    std::cout << "Hello";
}
void foo2() 
{ 
    std::cout << " wolrd!"; 
    
}


int main()
{
   
    //create array(of size 2) that can hold pointers to functions that does not return anything
    void (*arr[2])() = { foo, foo2};
    
    arr[0](); // calls foo 
    
    arr[1](); //calls foo1
    
    return 0;
}

方法2可以执行here

【讨论】:

  • 谢谢。您的方法 2 与我尝试过的方法非常接近,只是语法上的一个错误 (-: 。我已经修改了数组声明,其余的按我希望的那样工作。
  • @JimMack 不客气。
【解决方案2】:

您的函数指针数组需要正确的语法。 void(*func_ptr[])().

例子:

void func1() { std::cout << "Hallo" << std::endl; }
void func2() { std::cout << "World" << std::endl; }

// if you need a different signature for your functions like:
int func3(int n) { std::cout << "n1 " << n << std::endl; return n*2; }
int func4(int n) { std::cout << "n2 " << n << std::endl; return n*3; }

int main()
{
    // array of function pointer which
    // have no parameter and void as return value
    void(*func_ptr[])()={ func1, func2 };

    for ( unsigned int idx = 0; idx<2; idx++ )
    {
        func_ptr[idx]();
    }

    // array of function pointers with int return value and int as
    // parameter
    int(*func_ptr2[])(int)={ func3, func4 };

    for ( unsigned int idx = 0; idx<2; idx++ )
    {
        std::cout << "retval: " << func_ptr2[idx](6) << std::endl;
    }
}

【讨论】:

    【解决方案3】:

    我已经停止使用函数指针(尽管它们仍然有用)。 在使用函数时,我通常使用 std::function(和 lambdas)

    函数数组的代码如下所示。 我使用了 std::vector 但 std::array 固定大小也应该可以正常工作。

    #include <vector>
    #include <functional>
    #include <iostream>
    
    void some_function()
    {
        std::cout << "some function\n";
    }
    
    int main()
    {
        // std::function, abstraction of a function, function signature = template parameter, so void () is  function returning a void, no parameters
        // std::vector, runtime resizable array
        // constructor : 4 time a lambda function printing out hello world.
        std::vector<std::function<void()>> functions(4, [] { std::cout << "Hello World!\n"; } );
    
        // easy syntax to assign an existing function to an index
        functions[1] = some_function;
        
        // replace a function in the vector with another one (lambda)
        functions[2] = [] { std::cout << "booh\n"; };
    
        // call function at index 0
        functions[0]();
        std::cout << "\n\n";
    
        // or loop over all the functions and call them (classic for loop)
        for (std::size_t n = 0; n < functions.size(); ++n) functions[n]();
        std::cout << "\n\n";
    
        // or loop over all the functions (range based for loop)
        for (const auto& function : functions) function();
    
        return 0;
    }
    

    【讨论】:

    • 这绝对是现代方法。虽然我要提醒一句,通过函数调用需要一个虚函数调用,并且向量默认情况下会动态分配内存。对于某些应用程序来说可能不是问题,但我会在模拟或游戏等软件的热门路径中避免它们。
    • std::function 是函数指针的昂贵模拟。如果您不需要它提供的参数和返回类型匹配,那就是浪费时间和代码空间。将其标记为“现代方法”是营销炒作。
    • 我同意“现代”是 std::function 的错误标签。它是一种类型擦除的方式。当不需要擦除任何类型信息时,与一个好的旧函数指针相比​​,它会带来不必要的开销并且没有明显的好处。我并不是说它不好,但它不应该与任何函数的默认 goto 解决方案混淆
    • 我认为这是我的背景,我们经常使用 lambdas/std::functions,lambdas 的捕获功能(并将它们存储在函数中)在多线程环境中是可取的。没错,它们肯定不是零成本抽象,所以我也不会在嵌入式/时间关键的地方使用它们。以后我会避免使用“现代”这个词。我的立场是正确的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-12
    • 2023-03-11
    • 2013-03-05
    • 1970-01-01
    • 2014-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多