2015-09-24 45 views
0

鉴于打印功能:C++指针函数和非指针功能

void print(int i) 
{ 
    cout << i << endl; 
} 

为什么我们允许这样做的主要功能

void (*bar)(int); 
bar = &print; 

但不是这样的:

void fizz(int); 
fizz = print; 

但是,当涉及到函数参数时,我们可以将指针传递给函数n或该功能的副本:

void foo(void (*f)(int)) 
{ 
    (*f)(1); 
} 

void test(void f(int)) 
{ 
    f(1); 
} 

有人知道这些差异的原因吗?

+0

bar的定义是函数指针的正确语法,而fizz只是定义函数签名的语法。我不熟悉你的函数测试的语法,所以我希望别人可以清除它。 – Parappa

+0

请参阅http://stackoverflow.com/questions/26559758/function-to-function-pointer-decay – sfjac

+0

就像使用数组类型作为函数参数一样,它将转换为指向第一个元素的指针。显然这只能在函数声明中使用。不寻常的,但不是没有使用。 – Macmade

回答

0

函数指针可以指向任何具有相同参数和返回类型的函数。在上面的代码中,“bar”是指针,而bar=&print表示让bar指向print。但是,一个函数不能有=的功能。
函数指针的好处在于,只要函数具有相同的参数和返回类型,它就可以指向ANY函数。当函数指针作为另一个函数的参数时,这非常有用。
将函数用作参数时,传递的实际内容是函数的地址。函数不能被解引用(即不能作为函数传递)。我不太清楚,但看起来您的footest的实现是相同的。

+0

啊,我想没有星号,我通过了一个函数的副本。所以即使使用函数作为参数,函数仍然是一个地址。那么这意味着没有真正的理由在foo(void f(int))上使用void foo(void(* f)(int))? – Dobob

+0

相反,总是使用函数指针作为参数。它显示了事情应该是什么。 –

0

我会建议性病阅读起来::从函数C++ 11: http://en.cppreference.com/w/cpp/utility/functional/function

这将允许你做的越多,你打算什么,在哪里无效(INT)是指返回类型和列表您的功能参数:

void fizz(std::function<void(int)> f) 
{ 
    f(1); 
} 

功能现在是一流的数据类型。你甚至可以在没有任何痛苦的语法的情况下为类方法使用函数。您还可以在许多情况下使用自动进行惰性/动态替换。您也可以使用相同的设置来执行有趣的事情,例如异步启动功能。

auto used_to_call_fizz = fizz; 
used_to_call_fizz(f); 
std::async(used_to_call_fizz, f); 
+1

'auto'不是动态的。它基于分配静态地确定变量的类型,并且在标准没有明确定义表达的类型的地方是必需的,例如在'std :: bind'或lambda函数的情况下。 – CoffeeandCode

+0

auto是动态的,如果你改变了嘶嘶声的类型(比如说改变返回类型),你不需要重写该行,但是是的,你是正确的,它是在编译时确定的,因此类型安全。 – Ryan

+1

它在任何意义上都不是动态的。它是静态的。这就像调用“decltype”动态因为它可以确定多种不同类型':^) – CoffeeandCode

0

每个函数都有自己的地址,你可以看到它是一个array。功能void fizz(int)void print(int i)有不同的内存地址,所以fizz = print;会出错。但是您使用void (*bar)(int);,它显示了用于指向函数的函数指针。当您使用bar=&print时,它将初始化bar指针,然后得到正确的答案。顺便说一下,您可以使用bar=print,因为它们具有与array相同的内存地址。我希望这可以帮助你。