zoukankan      html  css  js  c++  java
  • 18.C++-[ ]操作符使用 、函数对象与普通函数区别(详解)

    在上章17.C++-string字符串类(详解)学习了string类,发现可以通过[ ]重载操作符访问每个字符

    比如:

    string s="SAD";
    
    for(int i=0,i< s.length();i++)
    cout<<s[i]<<endl;

    接下来,我们来自己写个[ ]重载操作符,来模拟string类

    #include <iostream>
    #include "string.h"
    
    class string
    {
    private:
       char *str;
       int len;
    
    public:
        string(const char *p=0)
        {
          if(p!=NULL)
          {
           len=strlen(p);
           str = new char[len];
           strcpy(str,p);
          }
          else
          {
            len=0;
            str = new char[1];
            str[0]='';
          }  
        }
        char& operator [](int i)
        {
        return str[i];
        }
    
        int length()
        {
         return len;
        }
    };
    
    int main()
    {
           string s="SAD";
           for(int i=0;i< s.length();i++)
           std::cout << s[i] << std::endl;
    
           return 0;
    } 

    运行打印:

    S
    A
    D

     

    函数对象

    • 函数对象是指该对象具备函数的行为
    • 函数对象,是通过()调用操作符声明得到的,然后便能通过函数方式来调用该对象了.
    • ()调用操作符可以定义不同参数的多个重载函数
    • ()调用操作符只能通过类的成员函数重载(不能通过全局函数)
    • 函数对象用于在工程中取代函数指针

    比如,定义一个函数对象t:

    class Test{
    public:
          void operator () (void)  //通过()重载操作符,来使对象具备函数的行为
         {
                  cout<<"hello"<<endl;
         }
    };
    
    int main()
    {
           Test t;
           t();          //打印"hello"
    } 

    函数对象与普通函数区别

    函数对象

    可以封装自己的成员以及其它函数,所以能够更好的面向对象.

    普通函数

    往往只具备逻辑关系,并且没有固定的成员,因为普通函数一被调用完后,里面的内容便被摧毁了,除非使用全局变量,但是全局变量又不具备封装性.

    接下来,我们来个普通函数函数对象的示例,便知道两者的区别了.

    需求如下:

    • 通过一个函数,来获取斐波那契数列每项的值
    • 每调用一次函数,便返回一个值
    • 可以重复使用

    普通函数实例:

    #include <iostream>           
    using namespace std;
    
    int cnt0=0;
    int cnt1=1;
    
    void fib_set(int n)          //设置斐波那契数列为哪一项,使fib()能重复使用
    {
         cnt0=0;
         cnt1=1;
         for(int i=0;i<n;i++)
         {
                int tmp=cnt1;
                cnt1=cnt0+cnt1;
                cnt0=tmp;
         }
    }
    
    int fib()              //计算出一项值
    {
      int tmp=cnt1;
      cnt1=cnt0+cnt1;
      cnt0=tmp;
    
      return tmp;
    }
    
    int main()
    {
      for(int i=0;i<5;i++)
      cout<<fib()<<endl;    //打印1~5项值
    
      fib_set(0);                  //从新设置项数位0
    
      for(int i=0;i<5;i++)
      cout<<fib()<<endl;    //再次打印1~5项值,使它能重复使用
    
      return 0;     
    } 

    运行打印:

    1
    1
    2
    3
    5
    1
    1
    2
    3
    5

    从上面代码可以看到,通过普通函数实现的需求,还需要两个全局变量才行,这在大项目里,完全不可取的,若项目里,像这样的模块多的话,那得有多少个全局变量啊?并且这些全局变量能够随意被破坏,没有一点封装性.

    接下来,通过函数对象来完成这个需求:

    #include <iostream>           
    using namespace std;
    
    class Fib{
    private:
           int cnt0;
           int cnt1;
    public:
           Fib(int n=0)
           {
              cnt0=0;
              cnt1=1;
           }
    
           void operator =(int n)
           {
              cnt0=0;
              cnt1=1;      
              for(int i=0;i<n;i++)
              {
                 int tmp=cnt1;
                 cnt1+=cnt0;
                 cnt0=tmp;
              }
           }
    
           int operator () ()
           {
                 int tmp=cnt1;
                 cnt1+=cnt0;
                 cnt0=tmp;
    
                  return cnt0;
           }
    
    };
    
    int main()
    {
      Fib  fib;
      for(int i=0;i<5;i++)
      cout<<fib()<<endl;    //打印1~5项值
    
      fib=0;                        //从新设置项数为0
    
      for(int i=0;i<5;i++)
      cout<<fib()<<endl;    //打印1~5项值
    
      return 0;     
    } 

    运行打印:

    1
    1
    2
    3
    5
    1
    1
    2
    3
    5

    从上面代码看到,使用函数对象后,便不需要使用全局变量了.

  • 相关阅读:
    linux 学习笔记1
    IIS请求筛选模块被配置为拒绝超过请求内容长度的请求
    ipod锁定后的恢复
    HTTP报文
    数据仓库概念
    数据挖掘概念
    大数据处理工具
    eclipse 4.3 汉化
    在CentOS中安装输入法
    编译Hadoop1.1.2eclipse插件并测试
  • 原文地址:https://www.cnblogs.com/lifexy/p/8647921.html
Copyright © 2011-2022 走看看