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

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

原文地址:https://www.cnblogs.com/lifexy/p/8647921.html