【问题标题】:Passing Function name as arguments to a function将函数名称作为参数传递给函数
【发布时间】:2011-06-15 10:26:13
【问题描述】:

是否可以将函数名(比如 A)作为参数传递给另一个函数(比如 B),然后从函数 B 调用函数 A。也就是说,函数名将存储在 B 中的变量中,并使用它调用名称在变量中的函数。例如 C++ 排序函数中的第一个和第二个参数是迭代器,但第三个参数是函数的名称。

【问题讨论】:

标签: c++ parameter-passing function-calls


【解决方案1】:

你可以为“任何可以用两个参数调用的东西”引入一个模板参数(这里是Pred):

template <typename Iter, typename Pred>
void mysort(Iter begin, Iter end, Pred predicate)
{
    --end;
    // ...
        if (predicate(*begin, *end))
        {
            // ...
        }
    // ...
}

然后您可以传递良好的旧 C 函数指针或 C++ 函数对象:

bool function(int x, int y)
{
    return x < y;
}

struct function_object
{
    bool operator()(int x, int y)
    {
        return x < y;
    }
};

int main()
{
    int numbers[] = {543, 6542654, 432514, 54, 45, 243};
    mysort(numbers + 0, numbers + 6, &function);
    mysort(numbers + 0, numbers + 6, function_object());
}

如您所见,函数对象是适当重载operator() 的类的对象。

【讨论】:

  • mysort(numbers + 0, numbers + 6, function); 也应该可以工作,因为“a function is implicitly convertible to a pointer to itself”。
  • 4-5个参数的函数可以用模板法吗?
  • @AlphaMineron 当然,参数Pred predicate 没有说明对Pred 类型的任何要求。只有通过使用if (predicate(*begin, *end)),编译器才会检查它是否可以使用 2 个参数调用。如果你需要 5 个参数,那么只需用 5 调用它。
【解决方案2】:

你应该阅读Function Pointers

【讨论】:

    【解决方案3】:

    函数指针的简单示例:

    #include <iostream>
    
    int apply(int (*fun)(int,int), int a, int b) {
        return (*fun)(a,b);
    }
    
    int add(int a, int b) {return a + b;}
    int multiply(int a, int b) {return a * b;}
    
    int main(int argc, const char* argv[]) {
        int added = apply(add, 2, 4);
        int multiplied = apply(multiply, 2, 4);
    
        std::cout << "added result: " << added << std::endl;
        std::cout << "multiplied result: " << multiplied << std::endl;
    }
    

    输出:

    added result: 6
    multiplied result: 8
    

    【讨论】:

      【解决方案4】:

      是的,不仅可以,而且用处也很大。

      从技术上讲,这些被称为function pointers

      从概念上讲,它们需要有回调机制。 event-driven 程序可能需要回调。例如,您的应用程序可能想知道何时单击鼠标按钮。在这种情况下,您需要向底层平台注册您对鼠标单击事件的兴趣,并告诉它应该在您的程序中调用什么方法/函数,以便您可以相应地执行代码。

      另一种这样的情况是程序具有异步执行模式。例如,如果要将文件写入硬盘,与进行算术计算相比,这是一个耗时的过程。因此,在将结果写入文件时,我们可能不想等待执行计算。程序可能会选择只在文件上调用 write 函数并返回并开始计算。同时,调用这个函数的调用者也可以指定一个 callback 函数。因此,当文件写入成功或失败时,都会调用回调函数并通知被调用者

      【讨论】:

        【解决方案5】:

        是的,这是可能的。从技术上讲,传递的并不完全是“名称”,而是实际上是指向正在传递的函数的指针。

        【讨论】: