有没有办法在 C++ 中将函数作为参数传递,就像在 C中函数可以作为参数传递的方式一样?我知道可以使用函数指针在 C 中将函数作为参数传递,我想知道在 C++ 中是否可以这样做。
5 回答
你可以像在 C 中那样做。但你也可以用 C++ 的方式来做(准确地说是 C++11):
// This function takes a function as an argument, which has no
// arguments and returns void.
void foo(std::function<void()> func)
{
// Call the function.
func();
}
您可以将普通函数传递给 foo()
void myFunc();
// ...
foo(myFunc);
但你也可以传递一个 lambda 表达式。例如:
foo([](){ /* code here */ });
您还可以传递函数对象(重载()
运算符的对象)。通常,您可以传递可以使用()
运算符调用的任何内容。
如果您改为使用 C 方式,那么您唯一可以传递的就是普通函数指针。
在 C++ 中可以像在 C 中一样将函数作为参数传递,但有一些区别:我们可以使用函数引用而不是指针、模板类型以及可变参数模板参数。例如:
函数参考:
在 C 中,我们没有通过引用传递对象的能力。然而,这在 C++ 中是可能的:
void f( void (&)() ) {}
f( h );
引用和指针之间的区别是微妙的,但很重要。例如,我们不能将NULL
或 0 传递给期望引用的函数;参数必须立即满足其类型。在大多数情况下,引用通常优于指针。
模板:
模板允许我们一般地将具有可变类型属性的函数作为参数传递:
template <class T, class U>
void f( T (&)( U ) ) {}
上面的签名接受具有任何返回类型或参数列表的函数(唯一的挫折是该函数必须接受一个参数)。
除了这个特性,我们还可以利用可变参数模板来允许具有可变长度参数列表的函数:
template <class T, class ...U>
void f( T (&)( U... ) ) {}
int h(int, int) { .. }
bool g(std::string) { .. }
f( h );
f( g );
如果我们使用,f
也可以使用完美转发U&&
:
template <class T, class ...U>
void f( T (&fun)( U&&...) ) {
// ...
fun( std::forward<U>(u)... );
}
还有一些 lambdas 通常与std::function<T(U)>
.
是的,函数指针在 C++ 中的工作方式与在 C 中的工作方式完全相同。
是的,像这样:
#include <stdio.h>
typedef void (*my_func)(int);
void do_something (my_func f)
{
f (10);
}
void square (int j)
{
printf ("squared: %d\n", j * j);
}
void cube (int j)
{
printf ("cubed: %d\n", j * j * j);
}
int main (int argc, char *argv[])
{
do_something (square);
do_something (cube);
}
输出是:
squared: 100
cubed: 1000
typedef 是为了使 do_something() 的语法更具可读性。
我想指出的是,由于您已经在使用 C++,因此使用虚函数实现同样的功能要简单得多。
是的,有可能。
我找到了一个工作示例程序(可以在线测试和编辑,并很好地说明了这个概念):http: //ideone.com/6kSTrp#view_edit_box
//this was taken from http://www.cprogramming.com/tutorial/function-pointers.html
#include <stdio.h>
void my_int_func(int x)
{
printf( "%d\n", x );
}
int main()
{
void (*foo)(int); //pointer to an int function
foo = &my_int_func;
/* call my_int_func (note that you do not need to write (*foo)(2) ) */
foo( 2 );
/* but if you want to, you may */
(*foo)( 2 );
return 0;
}