函数指针的使用,以及使用函数指针的好处

函数指针是指向函数的指针变量。 因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。程序在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。很多c++泛型算法以及linux库函数经常见到函数指针的使用。。

  1. 函数指针的声明:

    bool (*pf)(int, int);
    //pf指向一个函数,该函数的参数是两个int,返回值是bool类型

  2. 函数指针的初始化

    例如有这样一个函数:bool cmp(int a, int b);
    pf = cmp//注意cmp形参及返回值应与声明的的函数指针的类型匹配

  3. 调用函数指针

    bool b = pf(3,5);
    等价于直接调用:bool b = cmp(3,5);

  4. 函数指针使用的好处:

    单单用以上的调用的方法使用函数指针,除了使程序变得晦涩难懂别无意义。包括很多例程只是在阐明函数指针的使用方法,完全不符合函数指针的使用场合。那到底为什么还要使用函数指针呢!郁闷了很久,虽没完全理解的很深入,还是有所收获,总的来说,函数指针有两个方面的应用。
    (1)把指针函数当作形参传递给某些具有一定通用功能的模块。并封装成接口来提高代码的灵活性和后期维护的便捷性。
    一个经典的例子是泛型算法中的一个快速排序函数:

void qsort(void*base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));

参数:
1 待排序数组首地址

2 数组中待排序元素数量

扫描二维码关注公众号,回复: 3789722 查看本文章

3 各元素的占用空间大小

4 指向函数的指针,用于确定排序的规则
qsort设计时,底层开发者并不能确定调用者的需求,因此便采用函数指针的方法,在qsort内部通过函数指针调用传递过来的函数(这等同于在内部直接调用,但为了封装成接口,供调用者使用,采用函数指针的方法更好,这种机制与形参传递变量类似)
这里通过比较一个比较low的冒泡排序来说明一下qsort内部函数指针的实现机制:

#include<iostream>
using namespace std;
void sort(int arr[], int size, bool(*cmp)(int,int));
bool up(int a, int b);
bool down(int a, int b);
int main()
{
    int arr[10];
    for (int i = 0;i < 10;++i)
        cin >> arr[i];

    sort(arr, 10,down);

    for (int i = 0;i < 10;++i)
        cout << arr[i] << " ";
    return 0;
}
void sort(int arr[],int size,bool(*cmp)(int,int))//简单冒泡排序
{
    int temp;
    for (int i = 0;i < size-1; ++i)
    {
        for (int j = i;j < size-1;++j)
        {
            if (cmp(arr[i], arr[j + 1]))
            {
                temp = arr[i];
                arr[i] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}
bool up(int a, int b)
{
    if (a > b)
        return 1;
    else
        return 0;
}
bool down(int a, int b)
{
    if (a > b)
        return 0;
    else
        return 1;
}

调用者通过传入相应的函数指针来决定排序的规则,这里只是一个简单的例子,真正的函数指针的使用可以将实现同一功能的很多个模块统一起来标识,这样一来更容易后期的维护,系统结构更加清晰。或者归纳为:便于分层设计、利于系统抽象、降低耦合度以及使接口与实现分开。
该冒泡排序的通用性是不是稍微强大了一丢丢。。。。(其实此个例程中,也可以通过一个变量来决定使用什么样的排序规则,不过,我猜测,博大精深的库中很多场合不是通过一个变量能解决的(仅仅猜测哈。。而且后期修改的话是不需要动sort函数框架的。。)
(2)另外,有些地方必须使用函数函数指针才能完成给定的任务,如linux系统中的异步信号中断处理,当发生某一触发信号时,需要调用相应的处理函数,此时需要使用函数指针来实现。

void (*signal(int signum,void(* handler)(int)))(int);  

参数一为信号条件,第二个参数为一个函数指针,它所指向的函数需要一个整型参数,无返回值。
该函数的返回值也是一个函数指针,返回的指针所指向的函数有一个整型参数(一般不用)

猜你喜欢

转载自blog.csdn.net/Gouhailiang/article/details/74170670
今日推荐