1. 程式人生 > >函式指標、this指標、bind函式、成員函式指標

函式指標、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);                }