1. 程式人生 > 實用技巧 >第35課 函式物件分析(函式操作符()過載)

第35課 函式物件分析(函式操作符()過載)

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)函式物件用於在工程中取代函式指標---------避免使用原生指標