第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)函数对象用于在工程中取代函数指针---------避免使用原生指针

猜你喜欢

转载自www.cnblogs.com/liuyueyue/p/13379345.html
今日推荐