简体   繁体   English

C++ function 指针在声明和参数

[英]C++ function pointer at declaration and argument

I am confused about using C++ function pointers.我对使用 C++ function 指针感到困惑。

using fn_p1 = void(int);  // function pointer
using fn_p2 = void (*)(int);

void functional(fn_p1 f) {
    f(1);
}

void callback(int value){
    // do something
}

int main() {
    fn_p2 f = callback; //works
    fn_p1 f1 = static_cast<fn_p1>(f); //does not work
    fn_p1 f2 = callback; //does not work
    fn_p1 f2 = static_cast<fn_p1>(callback); //does not work

    functional(f);  // works, the argument is form of void(*)(int)
    f(1);           // works
    
    functional(*f);  // works, the argument is dereferenced, void(int)
    (*f)(1);         // works
    return 0;
}

I know there is no difference if you call a function pointer with f(1) , (*f)(1) , or (*****f)(1) .我知道如果你用f(1)(*f)(1)(*****f)(1)调用 function 指针没有区别。 I don't get how functional(f);我不明白functional(f); works but fn_p1 f1 = static_cast<fn_p1>(f);有效,但fn_p1 f1 = static_cast<fn_p1>(f); and its variants can not since they define the function pointer as using fn_p1 = void(int);及其变体不能,因为它们将 function 指针定义为using fn_p1 = void(int); . . Could anyone explain how the function pointer works or how the compiler deals with it?谁能解释 function 指针如何工作或编译器如何处理它?

The most useful error that the IDE should give you is on the line fn_p1 f2 = callback; IDE 应该给您的最有用的错误是fn_p1 f2 = callback; :

Illegal initializer (only variables can be initialized) [illegal_initializer]非法初始化器(只能初始化变量)[illegal_initializer]

(This is the message I get from clangd.) (这是我从clangd那里得到的信息。)

That means literally that an entity of type void(int) (or more in general someReturnType(someArgTypes...) ) is not a variable.从字面上看,这意味着void(int)类型的实体(或更一般的someReturnType(someArgTypes...) )不是变量。

Indeed, in C++ functions are not first class, which means that you can't pass them to function and don't get them in return from function; Indeed, in C++ functions are not first class, which means that you can't pass them to function and don't get them in return from function; when you think you are successfully doing so, you're in reality passing or taking back function pointers.当你认为你成功地这样做时,你实际上是在传递或收回 function 指针。

In other words there's no such a thing in C++ as "a function value".换句话说,C++ 中没有“function 值”这样的东西。 Functions are not values that you can assign to.函数不是您可以分配的值。

When you write当你写

fn_p1 f2 = callback; // assuming using fn_p1 = void(int);

you are truly trying to create a variable of type void(int) .您确实在尝试创建void(int)类型的变量。 But such a thing doesn't exist, hence the error.但是这样的事情不存在,因此错误。

The static_cast s don't work for fundamentally the same reason. static_cast的工作原理基本相同。


As regards至于

void functional(fn_p1 f) {
    f(1);
}

function-to-(function)pointer decaying is happening. 函数到(函数)指针衰减正在发生。 f is truly of type fn_p1* . f确实属于fn_p1*类型。

You can easily verify it by writing an invalid statement in functional in order to trigger a compiler error telling you what the type of f is, like this您可以通过在functional中编写无效语句来轻松验证它,以触发编译器错误,告诉您f的类型是什么,就像这样

void functional(fn_p1 f) {
    int foo = f;
    f(1);
}

Clangd answers this Clangd 回答了这个问题

Cannot initialize a variable of type 'int' with an lvalue of type 'fn_p1 ' (aka 'void ( )(int)') [init_conversion_failed]无法使用“fn_p1 ”类型的左值(又名“void ( )(int)”)初始化“int”类型的变量 [init_conversion_failed]

which indirectly tells you that f is of type fn_p1* , so you better write that instead of fn_p1 as the type of the parameter of functional , at least for clarity (similarly to how you should prefer writing T* instead of T[] as a parameter type in a function taking a c-style array of T s).它间接告诉您f的类型为fn_p1* ,因此您最好将其写为functional参数的类型不是fn_p1 ,至少为了清楚起见(类似于您应该更喜欢将T*而不是T[]写为function 中的参数类型采用T s 的 c 样式数组)。


If you truly want to assign functions to variables, you should look at lambdas , struct s+ operator() , std::function , and the topic of function objects in general.如果您真的想将函数分配给变量,您应该查看lambdasstruct s+ operator()std::function以及function 对象的主题。

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

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