zoukankan      html  css  js  c++  java
  • 第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)函数对象用于在工程中取代函数指针

  • 相关阅读:
    C#客户端程序Visual Studio远程调试
    VS2013如何转成VS2010且不会出现此项目与Visual Studio的当前版本不兼容的报错
    Windows控件的命名规范
    VS2010中如何将exe文件生成setup安装文件
    Altium Designer Summer 09的操作
    Java SE(一)——java基础
    Java SE(二)——java语言基础
    重写与重载的区别
    Altium Designer Summer 09——元器件的封装
    Java SE(四)——java 面向对象入门
  • 原文地址:https://www.cnblogs.com/hoiday/p/10166377.html
Copyright © 2011-2022 走看看