C++中函數調用操作符的重載


1,本博文講述函數對象問題;

 

2,客戶需求:

    1,編寫一個函數:

       1,函數可以獲得斐波那契數列每項的值;

       2,每調用一次返回一個值;

       3,函數可根據需要重復使用;

       4,代碼示例:

1 for(int i=0; i<10; i++)
2 {
3      cout << fib() << endl;
4 }

      

3,第一個解決方案編程實驗:

    1,main.cpp 文件:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 int fib()
 7 {
 8     static int a0 = 0;  // 記錄函數狀態;
 9     static int a1 = 1;
10     
11     int ret = a1;
12     
13     a1 = a0 + a1;  // 更新 a1 的值;
14     a0 = ret;  // a0 更新;
15     
16     return ret;
17 }
18 
19 
20 int main()
21 {
22     for(int i=0; i<5; i++)
23     {
24         cout << fib() << endl; //fib() 是帶狀態的函數,因為每次調用的結果是不同的,當輸入的參數是一樣的,返回結果必然是一樣的函數叫做無狀態函數;
25     }
26     
27     cout << endl;
28     
29     for(int i=0; i<5; i++)
30     {
31         cout << fib() << endl;
32     }
33     
34     return 0;
35 }

 2,輸出結果:

 1 1
 2 1
 3 2
 4 3
 5 5
 6 
 7 8
 8 13
 9 21
10 34
11 55

    3,帶狀態函數:每次調用的返回結果不同的函數,即相同的輸入參數,不同的返回結果;

 4,兩種方法實現帶狀態函數:

   1,是將函數內部要使用的變量用全局變量來代替,可以記錄上一次函數調用的狀態,但是代碼中建議不要使用全局變量;

   2,是將函數內部要使用的變量用靜態局部變量來代替;

 

4,存在的問題:

    1,函數一旦開始調用就無法重來:

       1,靜態局部變量處於函數內部,外界無法改變;

       2,函數為全局函數,是唯一的,無法多次獨立使用;

       3,無法指定某個具體的數列項作為初始值;

    2,當用全局變量來使用時,可以達到目的,但是要在調用函數之前設置全局變量初始值,這樣和用戶的要求不符合;

      

5,解決方案:

    1,函數對象:

       1,使用具體的類對象取代函數;

       2,該類的對象具備函數調用的行為;

           1,很了不起的行為;

       3,構造函數指定具體數列項的起始位置;

       4,多個對象相互獨立的求解數據項;

      

6,函數對象:

    1,函數調用操作符(()):

       1,只能通過類的成員函數重載;

       2,可以定義不同參數的多個重載函數;

       (3),C 和 C++ 中,函數調用操作符 “()” 其實是編譯器內置的操作符,它的地位同 “[]” 一致,可以被重載,重載后一個類的對象可以當做 函數來使用;

      

7,最終解決方案編程實驗:

    1,main.cpp 文件:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Fib
 7 {
 8     int a0;
 9     int a1;
10 public:
11     Fib()
12     {
13         a0 = 0;
14         a1 = 1;
15     }
16     
17     /* 這個函數實現的非常經典 */
18     Fib(int n)
19     {
20         a0 = 0;
21         a1 = 1;
22         
23         for(int i=2; i<=n; i++)
24         {
25             int t = a1;
26             
27             a1 = a0 + a1;
28             a0 = t;
29         }
30     }
31     
32     int operator () ()  // 重載函數調用操作符 (),這樣類的對象就可以當做函數來調用;
33     {
34         int ret = a1;
35     
36         a1 = a0 + a1;
37         a0 = ret;
38         
39         return ret;
40     }
41 };
42 
43 int main()
44 {
45     Fib fib;
46     
47     for(int i=0; i<10; i++)
48     {
49         cout << fib() << endl;  // fib 不是函數名,而是對象名,這里將對象當做函數調用;
50     }
51     
52     cout << endl;
53     
54     for(int i=0; i<5; i++)
55     {
56         cout << fib() << endl;
57     }
58     
59     cout << endl;
60     
61     Fib fib2(10);  // 第二個對象和第一個獨立,也就可以從頭開始了;
62     
63     for(int i=0; i<5; i++)
64     {
65         cout << fib2() << endl;
66     }
67     
68     return 0;
69 }

 2,輸出結果:

 1 1
 2 1
 3 2
 4 3
 5 5
 6 
 7 8
 8 13
 9 21
10 34
11 55
12 
13 5
14 8
15 13
16 21
17 34

    3,提供函數對象,通過私有成員變量來記錄函數調用狀態,意味着繞開了局部     變量和全局變量這樣的限制;

    4,帶狀態函數實現方法:

       1,用全局變量實現函數內部的使用變量;

       2,靜態局部變量;

       3,函數對象中的成員變量;

 

8,小結:

    1,函數調用操作符(())是可重載的;

    2,函數調用操作符只能通過類的成員函數重載;

       1,和 “=” 相同;

    3,函數調用操作符可以定義不同參數的多個重載函數;

    4,函數對象用於在工程中取代函數指針;

       1,實際的 C++ 工程項目中,我們要盡量少的使用原生的指針;

       2,字符串可以使用字符串類而不用字符數組,數組可以使用數組對象,函數指針可以用函數對象,這些對象都是用於在工程中取代指針;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM