考虑这个简单的程序:
#include <iostream>
void length(void){
std::cout<<"My length is void"<<std::endl;
}
void width(void){
std::cout<<"My width is void"<<std::endl;
}
int main(void){
std::cout<<"The program length is: "<<length<<std::endl;
std::cout<<"The program width is: "<<width<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出是:
The program length is: 1
The program width is: 1
Run Code Online (Sandbox Code Playgroud)
程序打印出来的数字是多少,基本上没有多少C++知识,这对我来说看起来更加pythonic语法,看起来好像应该打印函数地址.我这样说是因为这个问题最初是在为openGL练习一些非常基本的程序时出现的,
回调是在GLUT中注册的,例如:
void line(void){
//some code for line program ...
}
int main(int argc, char** argv){
//some more code;
glutDisplayFunc(line);
glutMainLoop();
}
Run Code Online (Sandbox Code Playgroud)
这几乎看起来好像我们正在传递函数的地址,但是,从上面的程序中可以清楚地知道这不是一个地址,指向函数的语法有点不同,如果是这样,这个函数如何被注册为打回来?我们传递的是 glutDisplayFunc什么?
并且,因为我想要注册一个已经传递参数的函数,我搜索python lambda函数的C++类比,并找到类似的lambda函数,但它没有成功:**
#include <iostream>
void line(int a, int b){
//some code that does some plotting in the display window
}
int main(int argc, char** argv){
auto callback = [](void)->void{
line(a,b);
};
glutDisplayFunc(callback);
glutMainLoop();
}
Run Code Online (Sandbox Code Playgroud)
这完全失败了,显示的错误是:
no suitable conversion function from "lambda []void ()->void" to "void (*)()" exists
Run Code Online (Sandbox Code Playgroud)
这是使用我的python类比,但这个问题的解决方案是什么?混淆的主要部分以粗体突出显示.
这几乎看起来好像我们正在传递函数的地址,但是,从上面的程序中可以清楚地看出这不是一个地址
你有事情倒退了.这并不是glutDisplayFunc在做奇怪的神奇事物; 它是std::cout.
是的,函数名称将转换为函数指针.operator<<iostreams和C++重载规则规则的重载组合最终导致<<将函数视为布尔值(是的,真的).因此,你<< length就等同于做<< true.
如果你想要地址,你可以void*在输出之前将函数指针强制转换为a :<< reinterpret_cast<void*>(&length)或者更简洁<< (void*)&length(虽然从技术上讲,这只是C++有条件地支持,几乎每个真正的编译器都允许这样做).
最后,在C++中,lambdas不是函数; 他们是对象.您不能将对象传递给需要函数指针的对象.您可以将无捕获的lambda转换为函数指针,但是对于捕获值的函数,您不能这样做.