很抱歉,如果之前有人询问,但我找不到它。
所以我试着自我教育模板和新的C ++ 11功能(主要是lambdas,我一直喜欢用其他语言)。
但是在我的测试中,我发现了一些我不知道它有效的东西,而我正试图理解它是如何工作的,但是无法弄明白......
以下代码:
template <class Func>
void Test( Func callback ) {
callback( 3 );
}
void Callback( int i ) {
std::cout << i << std::endl;
}
int main( int argc, char** argv ) {
Test( &Callback ); // this I was expecting to work, compiler will see its a pointer to a function
Test( Callback ); // this also works, but how?!
return 0;
}
如果我理解模板是如何工作的,基本上它们是编译器知道要构建什么的方案,所以第一次调用Test( &Callback );
我期望工作,因为编译器会看到模板接收到一个函数地址并假设参数应该是一个指针。
但是第二个电话是什么?假设是什么模板?一个功能的副本(如果这有意义的话)?
答案 0 :(得分:15)
函数可以隐式转换为指向自身的指针;这种转换几乎无处不在。 Test(Callback)
与Test(&Callback)
完全相同。没有区别。在这两种情况下,Func
都被推断为void(*)(int)
。
函数指针很奇怪。您可以在"Why do all these crazy function pointer definitions all work?"
中找到有关它们的更多信息答案 1 :(得分:3)
在C ++中,函数不是第一类对象,这意味着“函数作为值”在其中没有任何意义。这就是为什么函数名一直可以隐式转换为指向它的指针。
答案 2 :(得分:2)
函数可以隐式转换为函数指针。如果事实上没有办法获得函数值或引用。虽然奇怪的是你可以创建一个函数值类型,但你不能为它指定任何东西。
Here is code snippit演示了lambdas和各种回调如何与模板作出反应。
答案 3 :(得分:0)
在C ++ 11(以及boost和tr1)中,我们将std :: function作为模板类型来存储函子,lambda和函数。所以你绝对可以将函数值保存在std :: function类型的变量中。该变量也可以是“空”,意味着没有函数(引用)存储在其中。然后它无法被调用。
原始问题与C相反,C ++允许函数引用。另外,出于与C的兼容性原因,函数名称可以退化为函数指针。但是由于重载,C ++中的东西比C语言更“有趣”。