第35課 函式物件分析(函式操作符()過載)
阿新 • • 發佈:2020-07-26
1.為什麼需要函式物件
(1)案例
①編寫一個函式,使函式可以獲得斐波那契數列每項的值。
②每呼叫一次返回一個值
③函式可根據需要重複使用
【程式設計實驗】第一個解決方案
1 /*斐波那契數列:0、1、1、2、3、5、8、13、21、 2 遞迴的方法定義:F0=0,F1=1,Fn=F(n-1)+F(n-2)*/ 3 4 #include<iostream> 5 #include<string> 6 7 using namespace std; 8 9 int fib() 10 { 11 static int a0 = 0; //靜態區域性變數---記錄函式狀態 12 static int a1 = 1; //靜態區域性變數 13 14 int ret = a1; //第一次呼叫返回1,用a1初始化 15 16 a1 = a0 + a1; //a1更新下一次的值 17 a0 = ret; 18 19 return ret; //a0是上一次a1的值 20 } 21 22 int main() 23 { 24 //注意每次呼叫fib(),形式完全相同,但函式返回的結果不同! 25 26 //這叫有狀態函式,因為函式內部會通過static變數27 28 //記錄上次的狀態 29 30 for (int i = 0; i < 10; i++) 31 { 32 cout << fib() << endl; //1,1,2,3,5,8,13,21,34,55 33 } 34 35 cout << endl; 36 37 38 //函式不能回到初始狀態,會從新的狀態開始,繼續計算。---- //無法從第一項重新開始 39 for (int i = 0; i < 5; i++)40 { 41 cout << fib() << endl; //89,144,233,377,610,從上次結果開始 42 } 43 44 //fib()帶狀態函式:輸入引數一樣,但是每次返回值不同,要求函式返回的時候不會摧毀---靜態區域性變數實現 45 //區域性變數在函式返回的時候不會被摧毀 但是c++ 避免使用區域性變數 所以要使用類的靜態區域性變數 46 47 48 return 0; 49 }
(2)存在的問題
①函式一旦開始呼叫就無法重來(因為這種函式是有狀態的函式)
②靜態區域性變數處理函式內部,外界無法改變
③函式為全域性函式,是唯一的,無法多次獨立使用
④無法指定某個具體的數列項作為初始值
(3)解決方案:函式物件
①使用具體的類物件取代函式
②該類的物件具備函式呼叫的行為
③建構函式指定具體的數列項的起始位置
④多個物件相互獨立的求解數列項
2.函式物件
(1)函式呼叫操作符()----編譯器內建的操作符,與陣列訪問操作符一致,過載以後一個類物件可以當作函式使用
①只能通過類的成員函式過載
②可以定義不同引數的多個過載函式
1 #include<iostream> 2 #include<string> 3 4 //函式物件取代函式,該類的物件具備函式呼叫的行為 建構函式支援指定具體數列項的起始位置 5 //函式呼叫操作符() 只能通過類的成員函式過載,一個類的物件可以當做函式來使用 6 7 using namespace std; 8 9 class Fib 10 { 11 int a0; //建構函式進行初始化 12 int a1; 13 14 public: 15 16 // Fib() :a0(0), a1(1) {} 17 18 Fib() 19 { 20 a0 = 0; 21 a1 = 1; 22 } 23 24 Fib(int n) //指定某個項作為初始值 25 { 26 a0 = 0; 27 a1 = 1; 28 29 for (int i = 2; i < n; i++) 30 { 31 int t = a1; 32 33 a1 = a0 + a1; //推算從n項開始,a0 a1的值 34 a0 = t; 35 } 36 } 37 38 int operator() () //操作符過載----(過載操作符本質上是個函式),這種方式就像函式名呼叫函式一樣直觀! 39 { 40 int ret = a1; 41 a1 = a0 + a1; 42 a0 = ret; 43 return ret; 44 } 45 }; 46 47 48 int main() 49 { 50 Fib fib; //定義物件------取代函式 51 52 for (int i = 0; i < 10; i++) 53 { 54 cout << fib() << endl; //操作符過載----類的物件當作函式使用 55 } 56 57 cout << endl; 58 59 for (int i = 0; i <5; i++) 60 { 61 cout << fib() << endl; //1,1,2,3,5,8,13,21,34,55 62 } 63 64 Fib fib1; 65 66 for (int i = 0; i < 10; i++) 67 { 68 cout << fib1() << endl; //89,144,233,377,610,從上次結果開始 69 } 70 71 cout << endl; 72 73 Fib fib1(10); 74 75 for (int i = 0; i < 5; i++) 76 { 77 cout << fib1() << endl; //55,89,144,233,377 78 } 79 80 cout << endl; 81 82 return 0; 83 }
3.小結
(1)函式呼叫操作符()是可以過載的
(2)函式呼叫操作符()只能通過類的成員函式過載
(3)函式呼叫操作符()可以定義不同引數的多個過載函式
(4)函式物件用於在工程中取代函式指標---------避免使用原生指標