当前位置: 首页 > 知识库问答 >
问题:

函数指针的现代c替代

壤驷德宇
2023-03-14

我一直在使用函数指针,就像c中的这种格式。我偶尔会用到,我想知道c 11/14中是否引入了其他东西作为替代。

#include <iostream>
using namespace std;

void sayHello();
void someFunction(void f());

int main() {

    someFunction(sayHello);
    return 0;
}
void sayHello(){
    std::cout<<"\n Hello World";
}
void someFunction(void f()){
    f();
} 

我确实看了这个问题,但无法理解与传统使用函数指针相比的任何优势。另外,我想问,使用函数指针有什么问题(不推荐)吗,因为我从未见过任何人使用它们。或任何其他替代方案。

共有3个答案

宦子琪
2023-03-14

另外,我想问,使用函数指针有什么问题(不推荐)吗,因为我从未见过任何人使用它们。

是的。函数指针是非常糟糕的东西。首先,它们不支持泛型——所以你不能接受一个函数指针,比如说,接受std::向量

在C 11中有两种获取函数的方法。首先是使用模板。二是使用std::函数。

模板看起来有点像这样:

template<typename T> void func(F f) {
    f();
}

这里的主要优点是它接受任何类型的函数对象,包括函数指针,lambda,函子,绑定结果等,并且F可以具有任意数量的具有任何签名(包括模板)的函数调用重载,并且可以具有任何大小和任何绑定状态。所以它非常灵活。它也是最有效的,因为编译器可以内联运算符并直接在对象中传递状态。

int main() {
    int x = 5;
    func([=] { std::cout << x; });
}

这里的主要缺点是模板的常见缺点 - 它不适用于虚拟函数,必须在标题中定义。

另一种方法是标准::函数std::函数具有许多相同的优点 - 它可以是任何大小,绑定到任何状态,并且是任何可调用的,但交换了一对夫妇。主要是,签名在类型定义时是固定的,因此您不能使用 std::函数

基本上,函数指针非常有限,不能真正做任何有趣的事情,并且使API非常不灵活。他们可恶的语法是大海里的一泡尿,用一个模板别名来简化它是滑稽的,但毫无意义。

邵奇
2023-03-14

作为传统函数指针的替代,C11引入了模板别名,与可变模板相结合可以简化函数指针的正弦。下面是如何创建“template”函数指针的示例:

template <typename R, typename ...ARGS> using function = R(*)(ARGS...);

它可以这样使用:

void foo()                { ... }
int bar(int)              { ... }
double baz(double, float) { ... }

int main()
{
    function<void>                  f1 = foo;
    function<int, int>              f2 = bar;
    function<double, double, float> f3 = baz;

    f1(); f2({}); f3({}, {});
    return 0;
}

此外,它还可以灵活地处理函数重载:

void overloaded(int)      { std::cout << "int version\n"; }
void overloaded(double)   { std::cout << "double version\n"; }

int main()
{
    function<void, int>    f4 = overloaded;
    function<void, double> f5 = overloaded;

    f4({}); // int version
    f5({}); // double version
    return 0;
}

并且可以用作声明函数指针参数的一种非常简洁的方式:

void callCallback(function<int, int> callback, int value)
{
    std::cout << "Calling\n";
    std::cout << "v: " << callback(value) << '\n';
    std::cout << "Called\n";
}

int main()
{
    function<int, int> f2 = bar;
    callCallback(f2, {});
    return 0;
}

这个模板别名可以用作std::function的替代品,它既没有缺点也没有优点(这里有很好的解释)。

现场演示

简而言之,我认为模板别名与可变模板相结合是原始函数指针的一个好的、好的、整洁的和现代的C替代方案(毕竟这个别名仍然是函数指针),但是std::function是好的、好的、整洁的和现代的C语言,也有很好的优势需要考虑。坚持函数指针(或别名)或选择std::function取决于您的实现需求。

长孙景焕
2023-03-14

你提到的问题建议d::f油膏,但没有强调(或根本没有提到)它的价值时,结合d::b。

您的示例是最简单的,但假设您有一个

std::function<void (int, int)> f ;

函数指针可以做或多或少相同的事情。但假设您需要一个函数g(int),它是f,第二个参数绑定为0。使用函数指针您不能做很多事情,使用std::function您可以这样做:

std::function<void(int)> g = std::bind(f, _1, 0) ;
 类似资料:
  • 本文向大家介绍C语言 函数指针(指向函数的指针)详解,包括了C语言 函数指针(指向函数的指针)详解的使用技巧和注意事项,需要的朋友参考一下 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就

  • 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个 指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是 函数指针。 函数指针的定义形式为: returnType (*pointerName)(param list); returnType

  • 问题内容: 对于我的Java游戏服务器,我发送数据包的操作ID,该操作ID基本上告诉服务器该数据包的用途。我想将每个动作ID(一个整数)映射到一个函数。有没有不用开关就可以做到这一点的方法? 问题答案: 这个如何? (如果需要传递一些参数,请使用具有合适参数的函数定义自己的接口,并使用该接口代替Runnable)。

  • 问题内容: 我有一个大约十行代码的方法。我想创建更多功能完全相同的方法,只是进行少量计算会更改一行代码。这是传入函数指针以替换该行的理想应用程序,但是Java没有函数指针。我最好的选择是什么? 问题答案: 匿名内部阶级 假设你要传入的函数返回一个参数。 首先,如果你不能重用现有的接口,则必须定义一个以该函数作为其唯一成员的接口。 使用指针的方法将只接受实例,如下所示: 就像这样: 编辑:在Java

  • 我有一些C语言的代码,其中一个方法有一个函数指针作为参数。我正在尝试在我的Android应用程序中使用C代码。 我决定使用SWIG来完成生成所需java文件的所有工作。常规函数(没有函数指针作为参数的函数)一切都很好。 但是我不确定如何将我的JAVA方法作为回调传递给C函数。 下面是一个例子: 这是我的密码。h文件 这是我的密码。c文件 这是我的接口文件multiply-swigi 然后我运行以下

  • C++ 指针 在上一章中,我们已经了解了 C++ 中如何从函数返回数组,类似地,C++ 允许您从函数返回指针。为了做到这点,您必须声明一个返回指针的函数,如下所示: int * myFunction() { . . . } 另外,C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。 现在,让我们来看下面的函数,它会生成 10 个随机数,并使用表示指针的数组名(即第