2010-06-10 148 views
3

这是一个奇怪的标题。如果有人能够澄清我究竟在问什么,因为我不太确定我自己,我将不胜感激。如何在函数中传递函数?

我看对编程范式斯坦福视频(即老师真棒),我最多第五部影片的时候就开始这样做:

void *lSearch(void* key, void* base, int elemSize, int n, int (*cmpFn)(void*, void*)) 

当然,我对自己说,“喂,我不知道你可以声明一个函数并在以后定义它!“。所以我创建了我自己的C++测试版本。

int foo(int (*bar)(void*, void*)); 
int bar(void* a, void* b); 

int main(int argc, char** argv) 
{ 
    int *func = 0; 
    foo(bar); 

    cin.get(); 
    return 0; 
} 

int foo(int (*bar)(void*, void*)) 
{ 
    int c(10), d(15); 
    int *a = &c; 
    int *b = &d; 
    bar(a, b); 
    return 0; 
} 

int bar(void* a, void* b) 
{ 
    cout << "Why hello there." << endl; 
    return 0; 
} 

有关代码的问题是这样的:如果我声明功能int *barfoo参数失败,但不int (*bar)。为什么!?

此外,视频让我困惑的事实,他的lSearch定义

void* lSearch(/*params*/ , int (*cmpFn)(void*, void*))呼吁cmpFn的定义,但在调用lSearch功能

lSearch(/*params*/, intCmp); 

还调用定义的函数int intCmp(void* elem1, void* elem2);我当不明白那是如何工作的。为什么在lSearch中是叫做cmpFn的函数,但定义为intCmp,它的类型为int,而不是int*,仍然有效?为什么lSearch中的函数不必定义参数?

+1

是这样的: http://yoyodawgdawg.com/pics/yo-dawg-functions.jpg – 2010-06-10 18:03:09

+1

另请参阅此问题:http://stackoverflow.com/questions/2592137/。 – sbi 2010-06-10 18:10:35

+1

恭喜,你已经发现了更高阶的函数:) – fredoverflow 2010-06-10 18:24:22

回答

10

int (*cmpFn)(void*, void*)是一个函数指针 - 指向函数的指针,可以稍后调用。当你打电话给iSearch时,你会传递一个函数,它需要两个void*并返回一个int,并将其绑定到参数cmpFn。然后iSearch可以这样做int x = cmpFn(voidPtr1, voidPtr2);调用该函数,传入voidPtr1voidPtr2作为它的参数和存储返回值x

您可以只声明一个函数指针,并在同一个函数中使用它尝试一个简单的例子:

int test1(int x) {return x;} 
int test2(int x) {return x+1;} 

int main(int argc, char** argv) { 
    int (*fn)(int); // Function pointer named 'fn' that can hold a function that takes one int argument and returns an int 
    int rtn; 

    fn = test1; // Assign the 'test1' function to 'fn' 
    rtn = fn(4); // Call 'fn' ('test1') with the argument 4; it returns 4 and stores it in 'rtn' 

    fn = test2; // Assign the 'test2' function to 'fn' 
    rtn = fn(4); // Call 'fn' ('test2') with the argument 4; it returns 5 and stores it in 'rtn' 
} 

它失败如果声明int *bar,因为这不是一个函数指针,它只是一个指针到一个整数。函数指针的语法为rtn_type (*name)(param1_type, param2_type, ...)

4

有关代码的问题是这样的:如果我声明函数int *栏为Foo的参数失败了,但不是int(*栏)。为什么!?

因为你会为一个指向函数返回int*声明函数指针。请注意,在参数列表有一个功能和一个函数指针声明之间没有区别,既不存在一个阵列和一个指针声明之间在它们的差:

void f(void a()); 
void f(void(*a)()); 

void g(int a[]); 
void g(int *a); 

这些相当于 - 前两个具有它们的参数具有函数指针类型,而后两者的参数具有指针类型。

星号和圆括号的写法是因为它与参数列表之外的含义一致,当然函数指针和函数是不同的东西。

为什么在lSearch中,函数名为cmpFn,但定义为intCmp,它的类型为int,而不是int *且仍然有效?

星号表示它是指向函数的指针。星星不会附加到返回类型(这就是为什么paren首先出现在那里 - 要绑定到函数而不是返回类型)。

为什么lSearch中的函数不必定义参数?

函数指针的参数类型都是重要的。你可以给他们名字,但名字被忽略。

2

有大量专门用于函数指针的tutorials

您的第一个问题的答案是它首先绑定到类型的operator*的关联性。

在第二个示例中,lSearch执行的功能需要void*int。这正是如何申报intCmp

无论如何:函数指针在C++中并不重要。它们应该被包裹在Functor中(结构定义为operator()),您应该使用模板而不是void*

1

的语法:“一个指针,它有两个无效*参数并返回一个int一个函数”

int (*cmpFn)(void*, void*)

手段括号的位置只是语法的一部分。我怀疑他们是必要的,有助于区分在你有返回int* VS的int函数实例:

int* (*cmpFn)(void*, void*)

// Ambiguous - could be a pointer to a pointer to a function that returns int, or a pointer 
// to a function that returns int* 
int* *cmpFn(void*,void*) 

对于调用约定,认为cmpFn作为一个变量,持有一个函数。该名cmpFn是函数内部的变量的名称,但函数名本身可能是不同的,就像一个普通的变量:

void foo(int x) { 
    // Variable is called "x" inside the function 
} 

void main() { 
    int blah = 1; 
    foo(blah); // But it's called "blah" here 
} 

并配有功能:

void myfunction(void *ptr) { 
    // Does something. 
} 

void call_a_function(void (*func)(void*)) { 
    void* someptr; 
    func(someptr); // Function is called "func" here. 
} 

void main() { 
    call_a_function(myfunction); // But it's called "myfunction" here. 
}