第35课 函数对象分析(函数操作符()重载)

1. 为什么需要函数对象

(1)案例

  ①编写一个函数,使函数可以获得斐波那契数列每项的值

  ②每调用一次返回一个值

  ③函数可根据需要重复使用

      

 

【编程实验】第一个解决方案   35-1.cpp

#include <iostream>

 

using namespace std;

 

int fib()
{

    static int a0 = 0;

    static int a1 = 1;

    int ret = a1;

   

    a1 = a0 + a1;

    a0 = ret;

   

    return ret;

}

 

int main()
{

    for(int i = 0; i < 10; i++)

    {

        //注意每次调用fib(),形式完全相同,但函数返回的结果不同!

        //这叫有状态函数,因为函数内部会通过static变量

        //记录上次的状态

        cout << fib() << endl; //1,1,2,3,5,8,13,21,34,55

    }

   

    cout << endl;

 

    //函数不能回到初始状态,会从新的状态开始,继续计算。

    for(int i = 0; i < 5; i++)

    {

        cout << fib() << endl; //89,144,233,377,610,从上次结果开始

    }   

   

    return 0;

}

运行结果:

  

  

(2)存在的问题

  ①函数一旦开始调用无法重来(因为这种函数是有状态的函数

  ②静态局部变量处理函数内部外界无法改变

  ③函数为全局函数,是唯一的,无法多次独立使用

  ④无法指定某个具体的数列项作为初始值

 

(3)解决方案:函数对象

  ①使用具体的类对象取代函数

  ②该类的对象具备函数调用的行为

  ③构造函数指定具体的数列项的起始位置

  ④多个对象相互独立求解数列项

 

2. 函数对象

(1)函数调用操作符()

  ①只能通过类的成员函数重载

  ②可以定义不同参数的多个重载函数

 

【编程实验】最终解决方案   35-2.cpp

#include <iostream>

 

using namespace std;

 

class Fib
{

private:

    int a0;

    int a1;

   

public:

    Fib():a0(0),a1(1){}

  

    int operator()()  //operator()为函数名,后面的()为参数列表,这里为空

    {

        int ret = a1;

       

        a1 = a0 + a1;

        a0 = ret;

       

        return ret;

    }  

 

    Fib(int n)//设置初始化
    {

        a0 = 0;//先将初始化a0,a1

        a1 = 1;

       

        for(int i = 2; i<=n;i++)

        {

            int t = a1;

           

            a1 = a0 + a1;

            a0 = t;

        }

    }   

};

 

int main()
{

    Fib fib;

    for(int i = 0; i < 10; i++)
    {

        //fib是个对象,但因重载操作符(),可以用这个对象名调用函数(重载操作符

        //本质上是个函数),这种方式就像函数名调用函数一样直观!

        cout << fib() << endl; //1,1,2,3,5,8,13,21,34,55

    }

   

    cout << endl;

 

    for(int i = 0; i < 5; i++)
    {

        cout << fib() << endl; //89,144,233,377,610,从上次结果开始

    }   

   

    Fib fib2(10);//从第10个元素开始输出

   

    for(int i=0; i<5;i++)
    {

        cout << fib2() <<endl; //55,89,144,233,377

    }

   

    return 0;

}

运行结果:

  

 

3. 小结

(1)函数调用操作符()是可以重载的

(2)函数调用操作符()只能通过成员函数重载

(3)函数调用操作符()可以定义不同参数的多个重载函数

(4)函数对象用于在工程中取代函数指针

 

posted @ 2018-12-23 23:06  梦心之魂  阅读(223)  评论(0编辑  收藏  举报