1).函數指針原型:int (*myFuncVar)(int a, int b) ; //本質是一種變量,專門用做指向函數,變量名為myFuncVar。
我們可以這樣定義並賦值:
int add();
int (*myFuncVar)(int a, int b) = add;
也可以這樣定義並賦值:
int add();
int (*myFuncVar)(int a, int b);
myFuncVar = add;
2)作用:函數指針能用來:①當函數用作調用,成為了一般的函數調用 ② 做參數
下面是當函數用作調用:
//例1
1 #include<stdio.h> 2 #include<stdio.h> 3 int max(int x, int y){ return (x>y ? x : y); } // 定義帶參數max函數 4 5 int main() 6 { 7 int(*ptr)(int, int); // 定義函數指針變量ptr,參數為兩個int型數據 8 int a, b, c; 9 ptr = max; //指針變量指向函數首地址 10 scanf("%d%d", &a, &b); 11 c = (*ptr)(a, b); //等價於 c = max(a,b); 這樣就成了一般的函數調用了 12 printf("a=%d, b=%d, max=%d", a, b, c); 13 return 0; 14 }
下面是用作函數的參數
//例2
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 5 void A(int a, int b) 6 { 7 printf("我是A,a=%d,b=%d\n", a, b); 8 } 9 void B(int a, int b) 10 { 11 printf("我是B,a=%d,b=%d\n", a, b); 12 } 13 void C(int a, int b) 14 { 15 printf("我是C,a=%d,b=%d\n",a,b); 16 } 17 18 int myMianOp( void(*myFuncVar)(int a, int b) ) //函數指針當做函數的參數 19 { 20 myFuncVar(1, 2); 21 return 0; 22 } 23 void main() 24 { 25 myMianOp(A); //調用者 //A不僅為函數名,也是函數的首地址(也稱函數入口點) 26 myMianOp(B); //調用者 //B不僅為函數名,也是函數的首地址(也稱函數入口點) 27 myMianOp(C); //調用者 //C不僅為函數名,也是函數的首地址(也稱函數入口點) 28 29 system("pause"); 30 }
/***************************************************************************
輸出如下:
我是A,a=1,b=2
我是B,a=1,b=2
我是C,a=1,b=2
****************************************************************************/
3)C++里,多態是指基類和派生類里有重寫函數,而基類里的重寫函數前有virtual關鍵字修飾,當一個函數試圖調用這些重寫函數時,它會根據被送進來的參數對象來執行對應的重寫函數,如果參數是基類的對象就會運行基類里的重寫函數,如果參數是派生類的對象就會運行派生類的重寫函數。簡而言之,一個函數根據參數對象會有不同的運行形態。如果沒有virtual關鍵字修飾,則只會執行基類里的重寫函數。
重寫函數:必須在繼承里,基類和派生類有類型名、函數名、參數均一模一樣的成員函數,此類成員函數稱重寫函數。
虛函數:重寫函數里,如果在基類的重寫函數前頭用virtual關鍵字修飾,則稱這些函數名一樣的成員函數為虛函數。
因此,多態成立的三個條件為:要有繼承,虛函數重寫,一個帶參數且要試圖調用重寫函數的函數。
//例3 C++多態的實現
1 #include <iostream> 2 using namespace std; 3 4 5 6 7 class Parent 8 { 9 public: 10 Parent(int a=0) 11 { 12 this->a = a; 13 } 14 15 virtual void print_one() //1 動手腳 寫virtal關鍵字 會特殊處理 //虛函數表 16 { 17 cout<<"我是爹"<<endl; 18 } 19 virtual void print_tow() //1 動手腳 寫virtal關鍵字 會特殊處理 //虛函數表 20 { 21 cout<<"我是爹"<<endl; 22 } 23 private: 24 int a; 25 }; 26 27 class Child : public Parent 28 { 29 public: 30 Child(int a = 0, int b=0):Parent(a) 31 { 32 this->b = b; 33 } 34 35 virtual void print_one() 36 { 37 cout<<"我是兒子"<<endl; 38 } 39 private: 40 int b; 41 }; 42 43 void HowToPlay(Parent *base) 44 { 45 base->print_one(); //有多態發生 //2 動手腳 46 //效果:傳來子類對 執行子類的print_one函數 傳來父類對執行父類的print_one函數 47 //C++編譯器根本不需要區分是子類對象 還是父類對象 48 //父類對象和子類對象分步有vptr指針 , ==>虛函數表===>函數的入口地址 49 //遲綁定 (運行時的時候,c++編譯器才去判斷) 50 } 51 52 void main01() 53 { 54 55 Parent p1; //3 動手腳 提前布局 56 //用類定義對象的時候 C++編譯器會在對象中添加一個vptr指針 57 Child c1; //子類里面也有一個vptr指針 58 59 HowToPlay(&p1); 60 HowToPlay(&c1); 61 62 cout<<"hello..."<<endl; 63 system("pause"); 64 return ; 65 }