• [C++] 函数指针


    函数指针

    函数指针指向的是函数而非对象,和其他指针一样,函数指针指向某种特定类型。

    函数的类型由它的返回值类型和形参类型共同决定,与函数名无关。

    // function declare
    bool lengthCompare(const string&, const string&);
    // function type
    bool(const string&, const string&)
    // function pointer
    bool(*pf)(const string&, const string&);

    pf指向一个函数,该函数的参数是两个const string的引用,返回值是bool类型,*pf两边的括号必不可少

    使用函数指针

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

    pf = lengthCompare
    pf = &lengthCompare
    // 以上两种赋值方式等价

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

    bool b1 = pf("Hello", "Bye");
    bool b2 = (*pf)("Hello", "Bye");
    bool b3 = lengthCompare("Hello", "Bye");
    // 等价调用

    注意:指向不同函数类型的指针间不存在转换规则。所以要求函数指针指向的函数类型必须与定义函数指针时的类型相同。

    但是可以对函数指针赋予nullptr或者0来表示指针没有指向任何一个函数。

    当我们使用重载函数时,上下文必须清晰地界定到底应该使用哪个函数,指针类型(形参与返回值)必须与重载函数(新参与返回值)中的类型精确匹配。

    函数指针形参

    形参可以是指向函数的指针

    void useBigger(const string &s1, const string &s2, bool pf(const string &, const string &));
    // 第三个形参是函数类型,它会自动地转换成指向函数的指针
    void useBigger(const string &s1, const string &s2, bool (*pf)(const string &, const string &));
    // 等价声明:显式地将形参定义成指向函数的指针

    我们可以直接把函数作为实参使用,此时它会自动转换成指针

    useBigger(s1, s2, lengthCompare);

    使用类型别名和decltype简化使用函数指针

    // Func和Func2是函数类型
    typedef bool Func(const string&, const string&);
    typedef decltype(lengthCompare) Func2;
    
    // FuncP和FuncP2是指向函数的指针
    typedef bool(*FuncP)(const string&, const string&);
    typedef decltype(lengthCompare) *FuncP2;

    使用typedef定义自己的类型,Func和Func2是函数类型,FuncP和FuncP2是指针类型。

    decltype返回的类似是函数类型,所以只有在结果前面加上*才能得到指针。

    void useBigger(const string&, const string&, Func);
    void useBigger(const string&, const string&, FuncP2);

    返回指向函数的指针

    函数可以返回指向函数的指针,此时必须把返回类型写成指针类型。编译器不会自动将函数返回类型当成对应的指针类型处理

    using F = int(int*, int);
    // F为函数类型
    using PF = int(*)(int*, int);
    // FF为指针类型
    PF f1(int);
    F *f1(int);

    也可以直接声明f1

    int (*f1(int))(int*, int);

    f1有形参列表,说明f1是函数

    f1前面有*,说明f1返回一个指针

    指针类型本身也包含形参类型,所以指针指针指向函数,

    int表示指向的函数返回值类型为int

    下面使用尾置返回类型

    auto f1(int)->int(*)(int*, int);

    练习题6.54

    编写函数声明,令其接受两个int形参并且返回类型也是int,然后声明一个vector对象,令其元素是指向该函数的指针

    int func(int, int);
    // func的类型是int(int, int)
    
    using pf1 = decltype(func)*;
    using pf2 = int(*)(int, int);
    typedef decltype(func) *pf3;
    typedef int(*pf4)(int, int);
    
    vector<pf1> v1;
    vector<pf2> v2;
    vector<pf3> v3;
    vector<pf4> v4;

    练习题6.55

    编写4个函数,分别对两个int加、减、乘、除,在上一题创建的vector对象中保存指向这些函数的值

    int add(int a, int b) { return a + b; }
    int subtract(int a, int b) { return a - b; }
    int multiply(int a, int b) { return a * b; }
    int divide(int a, int b) { return a / b; }
    
    vector<decltype(func)*> fpvec = { add, subtract, multiply, divide };

    练习题6.56

    调用上述vector对象中的每个元素并输出其结果

    int main()
    {
        for (auto f : fpvec)
            cout << f(2, 2) << endl;
        return 0;
    }
    // output
    4
    0
    4
    1
    请按任意键继续. . .
  • 相关阅读:
    C语言实现单处理器的进程管理
    哈夫曼编码
    栈与队列的应用:停车场管理
    带括号的表达式求值
    表达式求值(无括号)
    处理代码异常
    在Pyhon中使用:网络编程 & 接口开发
    枚举函数(enumerate)
    【Redis】数据库相关操作
    数据库(新增数据、建立数据表、复制、对比表数据)
  • 原文地址:https://www.cnblogs.com/immjc/p/8193128.html
Copyright © 2020-2023  润新知