函数指针、this指针、bind函数、成员函数指针

一、函数指针( 不是类的成员函数 ):
    1、指针变量也可以指向一个函数。C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址,这个 函数入口地址就称为函数的指针

    2、函数指针的作用:
    (1)、调用函数:调用的时候,用该指针变量代替函数名即可
    (2)、将该函数作为其他函数的参数,即将该函数名作为其他函数的形参

    3、指向函数的指针变量 定义为:
        函数类型  (*指针变量名)  (函数形参列表);
        void (*p)  (int ,int);     //void是指针变量p指向的函数的类型;p是指向函数的指针变量;int,int是p所指向的函数中的形参的类型。

    4、举例:
        int max(int x, int y);   //函数声明
        int (*p) (int,int);    //定义指向函数的指针变量p
        p=max;              //使p指向函数max,即将函数max的入口地址赋给指针变量p

    5、 利用函数指针实现函数的调用
          p(3,5);    //相当于调用函数max(3,5)
        
    6、用指向函数的指针作为另一个函数的参数(函数指针作为其它函数的形参):
         函数指针作为函数的参数,将函数名传给其它函数的形参。这样就可以在调用一个函数的过程中根据给定的不同实参调用不同的函数。
         举例:利用这种方法编写一个求积分的通用函数,用该函数分别求以下3个函数的积分:
         (1+x)dx、(2x+3)dx、(5x)dx

        每次求定积分的函数都不一样,分别是(1+x、2x+3、5x)。可以编写一个通用函数intergral,它由三个形参,下限a、上限b以及指向函数的指针变量fun。该通用函数的原型是:
         double intergral(double a, double b, double (*fun) (double));
        然后分别编写3个函数f1、f2、f3分别求上面三个函数(1+x、2x+3、5x)值。然后分别调用intergral() 三次,每次把不同的函数入口地址(函数指针)传给intergral

二、this指针:
    1、在建立对象时,系统会为 每一个对象分配独立的存储空间,也就是给 每个对象中的 数据成员 都分配有自己独立的存储空间。如果对同一个类定义n个对象,则有n组同样大小的空间以存放对象中的数据成员。

    2、但对于成员函数来说,一个函数的代码段在内存中只有一份。也就是说,函数的代码段在内存中只有一份。也就是说, 同一个 类中的不同对象在调用自己的成员函数时, 其实它们调用的是同一段函数代码。

    3、当一个对象调用自己的成员函数时,如何 保证 成员函数中对数据成员的处理是针对自己的数据成员而不是其他对象的数据成员呢。这就用到this指针

    4、 在每一个成员 函数中都包含一个特殊的指针,这个指针的名字是固定的,称为 this。this的值是调用该成员函数的 对象的起始地址。在调用成员函数时,系统 隐式将对象的起始地址传递给成员函数(也就是将对象的起始地址传给每个成员函数的this指针),使this指针得到当前对象的地址。

    5、于是在成员函数中对数据成员的引用,就按照 this的指向找到对象的数据成员,实现对数据成员的操作。

    6、this 作用域是在类内部,当在类的 静态成员函数中访问类的 非静态成员的时候, 编译器会自动将对象本身的地址作为一个隐含 参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为 非静态成员函数隐含 形参,对各成员的访问均通过this进行。

    7、如有成员函数 int test(int a,int b);  
         其实成员函数的原型是: int test( 类名*this,int a,int b)
        第一个参数是指向该类对象的一个指针,我们在定义成员函数时没看见是因为这个参数在类中是隐含的。这样类对象的地址传递给了this


三、成员函数指针:
    1、创建一个成员函数指针:
      函数类型  (类名::*指针变量名)(函数形参列表)
     如: char (Student::*ptr) (int a, int b)
    
    2、使用成员函数指针:
        跟普通函数指针不同, 不能使用成员函数指针直接调用成员函数,而是要通过 .*->*运算符 将成员函数指针和类对象或指向对象的指针绑定起来。如:
        Student stu;
        Student *stu_ptr=&stu;
        int number;
        number=(stu.*ptr)(0,0);       //通过类对象调用ptr所指向的函数,并将实参0, 0传进去
        number=(stu_ptr->*ptr)(0,0);    //通过对象指针调用ptr所指向的函数,并将实参0, 0传进去  
        //如果不需要调用不需要传实参的函数,可以这么写:
         number=(stu.*ptr) ();       //通过类对象调用ptr所指向的函数
        number=(stu_ptr->*ptr) ();    //通过对象指针调用ptr所指向的函数

    3、将成员函数用作可调用对象(将成员函数用作某个函数的参数):成员函数不能直接调用,必须与某个对象绑定起来
          可以使用bind函数生成一个可调用对象(使用bind函数将成员函数与某个对象绑定起来):
         bind(&类名::成员函数名,对象(或指向对象的指针、引用、this指针),实参列表(与成员函数的形参列表对应))
         举例:
         Student stu;
         Student *stu_ptr=&stu;
         成员函数:
         int test(int a,int b);
         char getname();   

    4、绑定方法:
         (1)、 auto f=bind(&Student::test, stu, 5,6);    // 调用f()相当于调用Student::test(5,6)
         
         (2)、auto f=bind( &Student::test, stu, _1,_2);   //也可以绑定的时候不指定实参,用占位符来表示,在调用f的时候再指定实参
                调用: f(3,4);

         (3)、 auto f=bind(&Student::test, p, 4, 5,)

         (4)、假如在类的成员函数getname()中绑定类的另一个成员函数getnumber(),那么绑定的对象可以写成this。 但是调用f只能在这个成员函数中调用
                Student::char getname()
                {
                    auto f=bind(&Student::getnumber, this);
                }       

    5、调用方法:
        (1)、直接调用: 
                 bind(&Student::getnumber, this);
                bind(&Student::test, p, 4, 5);

        (2)、间接调用:
                通过调用f来调用

        (3)、将这个可调用对象作为某个函数的实参:在成员函数get_name()中将成员函数get_number()作为函数test()的形参:
                Student::char ge_tname()
                {
                    //第一种方法
                    test(bind(&Student::get_number, this));

                    //第二种方法
                    auto f=bind(&Student::get_number,this);
                    test(f);
                }















        








你可能感兴趣的:(函数指针、this指针、bind函数、成员函数指针)