• typedef 函数指针 数组 std::function


    1、整型指针

    typedef int* PINT;

    typedef int *PINT;

    2、结构体

    typedef struct {
      double data;
    }DATA,  *PDATA;  //DATA是结构体类型别名,PDATA是结构体指针类型的别名

    3、函数指针

    #include<iostream>
    using namespace std;
    
    void say()
    {
        cout << "hello world" << endl;
    }
    
    int main()
    {
        void (*p)() = &say; //声明函数指针局部变量并初始化
        (*p)();//或p();
        return 0;
    }

    函数名类似数组名。
      int a[100];定义了数组变量a,a是int [100]类型,是个数组类型。但int *p = a;竟可以把变量a直接赋给int*型变量p,但两者类型是不一样的。这是因为其中包含隐式的转换,a转换为了指向数组地址的指针常量,即int* const类型 。不含隐式转换的写法应该这样:int *p = &a[0];             

      而函数void say();声明了函数say,say是void (void)类型,是个函数类型。上例的函数指针p可以 p=&say或p=say赋值。p=say时,say隐式转换为了指向函数地址的函数指针常量,即void say(* const)()类型。调用时也可进行反向转换,所以p();或(*p)();都可以调用函数!

    可用typedf声明函数指针类型

    typedef void (*)() S; //error,格式不正确
    typedef void (*S)(); //ok!

    举例:

    #include<iostream>
    using namespace std;
    
    void say1()
    {
        cout << "say1" << endl;
    }
    
    void say2()
    {
        cout << "say2" << endl;
    }
    
    int main()
    {
        typedef void (*SAY)(); //声明局部类型
        SAY s; 
        s = say1;
        s(); //或 (*s)();
        (s = say2)(); //直接调用
        return 0;
    }

    这里是在main函数里声明的局部类型。当然,也可放在全局或类作用域中

    C++11:也可以用std::function 。类模版 std::function是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标进行存储、复制、和调用操作,这些目标包括函数、lambda表达式、绑定表达式、以及其它函数对象等。需#include <functional>

    //接上例
    #include <functional>
    int main()
    {
      std::function<void ()> sf;
      sf = &say1;
      sf();
      sf = &say2;//也可以sf = say2
      sf();            
      return 0;  
    }

    4、函数指针数组

      先说一下,[]的优先级很高的,和()  .  ->这3个同处于最高优先级

    void ((*p)[2])();//编译出错:'p' 数组元素类型不能是函数
    void (*p[2])() = {say1, say2}; //ok;
    p[0]();
    (*p[1])();

    上面,p是一个数组,含两个元素,元素类型是函数指针void (*)()  。

    //不建议
    typedef void (*S[2])();
    cout << sizeof(S) << endl;//8
    S a = {say1, say2};
    
    //建议,更易懂
    typedef void (*S)();
    S a[2] = {say1, say2};

    4、返回值、形参含函数指针

    int (*S)(int i, void (*p)()); //声明一个函数指针S,指向一函数。该函数返回值类型为int,有两个参数:int变量i和函数指针p。

    int* (*r)() (*S[2])(void (*p1)(), int& (*p2[3])(int*, int*));//声明一数组,然而会编译错误,这种写法是不对的。

    上面太复杂,编译器无法正常处理,你甚至可以编写更复杂的声明。用typedef可简化声明:

    typedef int* (*RTN)();// 是一个函数指针
    typedef void (*P1)();//参数1:也是函数指针
    typedef int& (*P2)(int*, int*); // 参数2
    
    typedef RTN (*S)(P1, P2[3]);
    S a[2];//声明

    若想定义一个函数指针pFoo,该指针所指向的函数也返回一个函数指针(类型是int (*)() )。

    那么你不应该这么写 int (*)() (*pFoo)();  

    也不应该这么写 int (*pFoo)()(); ,不能按值直接返回函数int (void)

    而应该这么写

    int (*(*pFoo)())();

    不同于 Linux中的signal函数原型就是: void (*signal(int, void(*)(int)))(int); ,signal是一个函数,而pFoo是一个指针。。注意两者括号包含区别~

    5、成员函数指针

    class Base
    {
    public:
      int m_a;
      void foo(){}
      static void sfoo(){} //注意:static修饰的是函数,不是返回值
    }

    int (Base::*pa) = &Base::m_a;
    void (Base::*f1)() = &Base::foo; //注意,*在::后面
    void (*f2)() = &Base::sfoo(); //注意static成员的指针不需指定作用域,可以向普通函数那样调用
    std::function<>

    #include <iostream>
    using namespace std;
    
    class AA
    {
    public:
        int m_a = 4;
        void f1()
        {
            cout << "AA::f1()" << endl;
        }
        void f2()
        {
            cout << "AA::f2()" << endl;
        }
    };
    
    void main(void)
    {
        AA aa;
    
        int (AA::*pa) = &AA::m_a;
        cout << aa.*pa << endl;//4
    
        void (AA::*f)() = NULL;
        f = &AA::f1;
        (aa.*f)();//AA::f1()
        f = &AA::f2;
        (aa.*f)();//AA::f2()
    }

    std::function需用到std::bind  ---VS2013一直编译出错, sigh~

    #include <functional>
    class T
    {
        public:
            void foo(int a){cout << "a: " << a << endl;}
    };
    
    
    int main()
    {
        T t;
    
        //方法1
        std::function<void (int)> sf = std::bind(&T::foo, &t, 5);
        sf();
        //方法2:  
        std::function<void (const &, int)> sf2 = std::bind(&T::foo);
        sf2(t, 5);   
        return 0;  
    }

    用typedef化繁为简,声明时可大大简化代码,且更易读!

  • 相关阅读:
    第十二周工作总结
    第八周工作总结
    冲刺2
    冲刺1
    用户场景分析
    用户场景分析
    水王在哪
    课堂练习-4个数的和
    《大道至简》第一章读后感
    ELF Format 笔记(三)—— Section Types
  • 原文地址:https://www.cnblogs.com/sfqtsh/p/5137366.html
Copyright © 2020-2023  润新知