zoukankan      html  css  js  c++  java
  • 函数指针(函数指针作为函数形参/函数类型作为函数返回类型)

    函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数

     1 #include<stdio.h>
     2 int max(int x,int y){return (x>y? x:y);}
     3 int main()
     4 {
     5     int (*ptr)(int, int);
     6     int a, b, c;
     7     ptr = max;
     8     scanf("%d%d", &a, &b);
     9     c = (*ptr)(a,b);
    10     printf("a=%d, b=%d, max=%d", a, b, c);
    11     return 0;
    12 }

    以上来自百度百科

    函数指针指向的是函数而非对象。和其他指针一样,函数指针指向某种特定类型。函数的类型由它的返回类型和形参类型共同决定,与函数名无关:

    bool length_compare(const string &, const string &);

    该函数的类型是 bool(const string &, const string &);想要声明一个指向该函数的指针,只要用指针替换函数名即可:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 bool leng_compare(const string &s1, const string &s2){
     5     return s1.size() > s2.size();
     6 }
     7 
     8 int main(void){
     9     //pf指向一个函数,该函数的参数是两个 const string 的引用,返回值是 bool 类型
    10     bool (*pf) (const string &, const string &);//未初始化
    11     return 0;
    12 }

    注意 *pf 两端的括号必不可少的。如果不写这对括号,则 pf 是一个返回值为 bool 指针的函数。

    使用指针函数:

    当我们把函数名作为一个值使用时,该函数自动地转换成指针:

    #include <iostream>
    using namespace std;
    
    bool leng_compare(const string &s1, const string &s2){
        return s1.size() > s2.size();
    }
    
    int main(void){
        //pf指向一个函数,该函数的参数是两个 const string 的引用,返回值是 bool 类型
        bool (*pf) (const string &, const string &);//未初始化
        pf = leng_compare;//pf指向名为 leng_compare 的函数
        cout << &pf << endl;
        cout << *pf << endl;
        cout << pf << endl;
    
        pf = &leng_compare;//和上面的那条赋值语句是等价的,即取地址符是可选的
        cout << &pf << endl;
        cout << *pf << endl;
        cout << pf << endl;
        return 0;
    }

    此外,我们还能直接使用指向函数的指针调用该函数,无需提前解引用指针:

    #include <iostream>
    using namespace std;
    
    bool leng_compare(const string &s1, const string &s2){
        return s1.size() > s2.size();
    }
    
    int main(void){
        //pf指向一个函数,该函数的参数是两个 const string 的引用,返回值是 bool 类型
        bool (*pf) (const string &, const string &);//未初始化
        pf = leng_compare;//pf指向名为 leng_compare 的函数
        bool flag1 = pf("acfjls", "fjsl");//调用leng_compare函数
        bool flag2 = (*pf)("fjlsfld", "jfs");//一个等价调用
        bool flag3 = leng_compare("fjslfjs", "jfkdl");//另一个等价调用
        return 0;
    }

    指向不同函数类型的指针间不存在转换规则。但是和往常一样,我们可以为函数指针赋一个 nullptr 或者值为 0 的常量表达式,表示该指针没有指向任何一个函数。

    重载函数的指针:

    当我们使用重载函数的指针时,上下文必须清晰地界定到底应该选用哪个函数。编译器通过指针类型确定选用哪个函数,指针类型必须与重载汉萨中的某一个精确匹配:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int gel(int* x){}
     5 
     6 int gel(unsigned int x){}
     7 
     8 int main(void){
     9     int cnt = gel(1);//单独函数调用是可以不是精确匹配,只要能有最佳匹配即可
    10     // int (*pf1)(int) = gel;//错误:形参列表不能精确匹配
    11     // double (*pf2)(int*) = gel;//错误:和第一个gel函数返回类型不匹配,和第二个gel函数形参不匹配
    12     int (*pf3)(unsigned int) = gel;//正确
    13     return 0;
    14 }

    函数指针形参:

    和数组类似,虽然不能定义函数类型的形参,但是形参可以是指向函数的指针。此时形参看起来是函数类型,实际上却是当成指针使用:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 bool length_compare(const string &, const string &){}
     5 
     6 //第三个形参是函数类型,它会自动转换成指向函数的指针
     7 void max(const string &s1, const string &s2, bool pf(const string &, const string &)){}
     8 //等价声定义,显示地将形参定义成指向函数的指针
     9 // void max(const string &s1, const string &s2, bool (*pf)(const string &, const string &)){};
    10 
    11 int main(void){
    12     max("fjs", "jfls", length_compare);//把函数当作为实参使用,此时它会自动地转换成指针
    13     return 0;
    14 }

    可以使用 typedef 定义自己的类,简化函数使用函数指针:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 bool length_compare(const string &, const string &){}
     5 
     6 // gel1 和 gel2 是等价的函数类型
     7 typedef bool gel1(const string &, const string &);
     8 typedef decltype(length_compare) gel2;
     9 
    10 //gel3 和 gel4 是等价的指针类型
    11 typedef bool(*gel3)(const string &, const string &);
    12 typedef decltype(length_compare) *gel4;
    13 
    14 //需要注意的是这里的 decltype 返回的是函数类型,此时不会将函数类型自动转换成指针类型,只有在 decltype 返回结果前加上 * 才能得到指针
    15 
    16 void max(const string &s1, const string &s2, gel1){}//编译器自动将gel1转换成指针类型了
    17 
    18 // void max(const string &s1, const string &s2, gel3){}//等价声明
    19 
    20 int main(void){
    21     max("fjs", "jfls", length_compare);//把函数当作为实参使用,此时它会自动地转换成指针
    22     return 0;
    23 }

    返回指向函数的指针:

    和数组类似,虽然不能返回一个函数,但是能返回指向函数类型的指针。然而,我们必须把返回类型写成指针的形式,编译器不会自动地将函数返回类型当成对应的指针类型处理。而想要声明一个返回函数指针的函数,可以直接声明,使用类型别名,尾置类型等:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 using gel1 = int(int*, int);//gel1是函数类型,不是指向函数的指针
     5 using gel2 = int(*)(int*, int);//gel2是指向函数的指针
     6 // typedef int (*gel3)(int*, int);//gel2的等价类型
     7 
     8 // gel1 lou(int x);//错误:gel1是函数类型,不是指针类型
     9 gel2 lou(int x);
    10 gel1* lou(int x);
    11 int (*lou(int x))(int *, int);//不使用类型别名,直接声明
    12 auto lou(int) -> int (*)(int *, int);//使用尾置返回类型
    13 
    14 int main(void){
    15     return 0;
    16 }

    使用 decltype:

    当我们明确知道返回的函数是哪一个,就能使用 decltype 简化书写函数指针返回类型的过程,需要注意的是 decltype 返回的不是指针,需要添加 *,这点和数组是一样的:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int gel(int *, int);
     5 
     6 decltype(gel) *lou(int x);//注意这里的*不能落掉
     7 
     8 int main(void){
     9     return 0;
    10 }
  • 相关阅读:
    javascript之全局函数
    讲真,MySQL索引优化看这篇文章就够了
    aws亚马逊磁盘扩展卷步骤
    google支付回调验证(备用)
    Linux TCP状态TIME_WAIT 过多的处理
    MySQL索引优化分析
    CSS使图片变模糊,亲测非常好用
    linux ss 命令用法说明
    php一行代码获取本周一,本周日,上周一,上周日,本月一日,本月最后一日,上月一日,上月最后一日日期
    有哪些你追了很多女生才明白的道理?
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/8067430.html
Copyright © 2011-2022 走看看