zoukankan      html  css  js  c++  java
  • C/C++中的函数指针的使用与总结

    概要:

    • 函数指针介绍
    • typedef简化函数指针的定义
    • 指向函数的指针的初始化和赋值
    • 通过指针调用函数
    • 函数指针形参
    • 返回指向函数的指针
    • 指向重载函数的指针

    参考《C++ Primer》 第五版


     

    • 函数指针介绍

    函数指针是C++中比较灵活而且重要的部分,对于软件的灵活度上有很大的帮助 !

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

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

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

    bool (*pf)(const string&, const string&);//未初始化

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

    //声明一个名为pf的函数,该函数返回bool*
    bool *pf(const string &, const string &);

     

    • typedef简化函数指针的定义

    现在我们来定义三个函数指针:

    bool(*pf1)(const string &, const string &);
    bool(*pf2)(const string &, const string &);
    bool(*pf3)(const string &, const string &);

     

    有没有发现一个问题,每次定义都需要这么长,有没有好的办法呢,当然是有的,我们可以用到typedef:

    typedef bool(*cmpFcn)(const string &, const string &);
    //bool(*pf1)(const string &, const string &);
    //bool(*pf2)(const string &, const string &);
    //bool(*pf3)(const string &, const string &);
    cmpFcn pf1;
    cmpFcn pf2;
    cmpFcn pf3;

     


     

    • 指向函数的指针的初始化和赋值

    函数指针的赋值:

    pf = lengthCompare ;
    pf = &lengthCompare ;

    因为在C/C++里函数名就是地址,所以以上两者都等价,都可以给函数指针赋值。


     

    • 通过指针调用函数

    可以直接使用指向函数的指针调用函数,无须提前解引用:

    bool b1=pf("hello","goodbye");
    bool b2=(*pf)("hello","goodbye");
    bool b3=LengthCompare("hello","goodbye");
    //三个等价调用

    指向不同函数类型的指针之间不存在转换规则。

    我们可以为函数指针赋一个 nullptr或者0 的整型常量表达式,表示该指针没有指向任何一个函数。

    bool lengthCompare(const string &s1, const string &s2) {
        return s1.size() == s2.size();
    }
    
    string::size_type sumLength(const string &s1, const string &s2) {
        return s1.size() + s2.size();
    }
    bool cstringCompare(char *s1, char *s2) {
        return strlen(s1) == strlen(s2);
    }
    
    pf1 = 0;
    pf2 = lengthCompare;
    //pf3 = sumLength;
    //pf4 = cstringCompare;

    如果函数返回类型不匹配(如上)、或者形参不匹配,也会报错!

     


     

    • 函数指针形参

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

    #include<iostream>
    #include<string>
    using namespace std;
    typedef bool(*cmpFcn)(const string &, const string &);
    //bool(*pf1)(const string &, const string &);
    //bool(*pf2)(const string &, const string &);
    //bool(*pf3)(const string &, const string &);
    bool lengthCompare(const string &s1, const string &s2) {
        return s1.size() == s2.size();
    }//第三个形参是函数类型,它会自动地转成指向函数类型的指针
    void useBigger(const string &s1, const string &s2, bool(*pf)(const string&, const string&)) {
        cout << pf(s1, s2) << endl;
    }
    
    int main()
    {    
        cmpFcn pf = lengthCompare;
        useBigger("hi", "func", pf);
        system("pause");
        return 0;
    }

     


     

     

    • 返回指向函数的指针

    和数组类似,虽然不能返回一个函数,但是能返回指向函数类型的指针,然而我们必须把返回类型写成指针形式,编译器不会自动地将函数返回类型当成对应的指针类型处理。

    #include<iostream>
    #include<string>
    #include<vector>
    using namespace std;
    
    int demo(int *p, int a) {
        return 12;
    }
    
    // ff是一个函数,有一个形参x,返回结果是一个函数指针int(*)(int *,int)
    int (*ff(int x))(int *, int) {
        cout << x << endl;
        return demo;
    }
    
    int main()
    {    
        int a = 5;
        cout << ff(2)(&a, a)<< endl;
        system("pause");
        return 0;
    }

    同样,要想声明一个返回函数类型的指针,最简单的方法是使用类型别名:

    typedef int (*PF)(int *, int);

    PF是一个函数指针,指向的函数有两个形参。

    于是就可以这么写了:

    // ff是一个函数,有一个形参x,返回结果是一个函数指针int(*)(int *,int)
    //int(*ff(int x))(int *, int) {
    //    cout << x << endl;
    //    return demo;
    //}
    
    PF ff(int x) {
        cout << x << endl;
        return demo;
    }

     

    • 指向重载函数的指针

    编译器通过指针类型决定选取那个函数,指针类型必须与重载函数中的一个精确匹配

    #include<iostream>
    #include<string>
    #include<vector>
    using namespace std;
    void ff(vector<double> vec) {
        cout << "ff(vector<double vec)" << endl;
    }
    
    void ff(unsigned int x) {
        cout << "ff(unsigned int x)" << endl;
    }
    
    int main()
    {    
        //void(*pf)(int x) = &ff;    报错
        void (*pf)(unsigned int x) = &ff;
        //double (*pf2)(vector<double>) = &ff;   报错
        void (*pf2)(vector<double>) = &ff;
        system("pause");
        return 0;
    }

     

  • 相关阅读:
    了解DockerFile
    容器数据卷
    Docker镜像讲解
    Java语法学习笔记:多态
    决策树之分类与回归
    python数据分析回归算法
    python之斐波那契序列算法的总结
    pandas 关于数据分组和聚合
    pandas中关于数据合并join,merge
    scrapy爬虫之断点续爬,增量爬取,断网急救
  • 原文地址:https://www.cnblogs.com/Mered1th/p/10502633.html
Copyright © 2011-2022 走看看