考虑以下简单程序:
#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;
}
该程序的输出为:
The program length is: 1
The program width is: 1
程序输出的数字是什么,并且尤其是对C ++基本上不了解,所以对我来说这看起来更像Python语法,看起来好像应该打印函数地址。我说这是因为,这个问题最初是在为openGL练习一些非常基本的程序时出现的,
回调已在GLUT中注册,类似于:
void line(void){
//some code for line program ...
}
int main(int argc, char** argv){
//some more code;
glutDisplayFunc(line);
glutMainLoop();
}
似乎我们正在传递函数的地址,但是,显然从上面的程序中,这不是地址,并且函数指针的语法有些不同,如果是的话,该函数正在注册以进行回调吗? glutDisplayFunc
是什么?
并且,由于我想注册一个已传递参数的函数,因此我在C ++类比中搜索了python lambda函数,并发现了类似的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();
}
这完全失败,显示的错误是:
no suitable conversion function from "lambda []void ()->void" to "void (*)()" exists
这是使用我的python类比,但是该问题的解决方案是什么?混乱的主要部分以粗体突出显示。
答案 0 :(得分:6)
似乎我们正在传递函数的地址,但是,显然从上述程序中,这不是地址
您的事情倒退了。不是glutDisplayFunc
在做怪异的魔术;是std::cout
。
是的,函数名称将转换为函数指针。 operator<<
iostream重载和C ++重载解析规则的结合最终导致<<
将函数视为布尔值(是的,确实)。因此,您的<< length
等价于<< true
。
如果需要地址,可以在输出之前将函数指针转换为void*
:<< reinterpret_cast<void*>(&length)
或更简洁的<< (void*)&length
(尽管从技术上讲,这仅受C ++支持) ,几乎每个真正的编译器都允许这样做。
最后,在C ++中,lambda不是函数。它们是对象。您不能将对象传递给需要函数指针的对象。您可以将无捕获的lambda转换为函数指针,但不能对捕获值的函数执行此操作。