C++ 之函数调用操作符和函数对象

本文介绍了如何为类类型对象重载函数调用操作符,创建函数对象,并使用函数适配器来增加算法的灵活性。文章还展示了如何利用函数对象进行算术、关系和逻辑运算,并提供了具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可以为类类型的对象重载函数调用操作符。一般为表示操作的类重载函数调用操作符;


函数调用操作符必须声明为函数成员。一个类可以定义函数调用操作符的多个版本,由形参的数目或类型加以区别;


定义了调用操作符的类,其对象常称为为函数对象(function object)即它们是行为类似函数的对象;


eg.


struct absInit
{
    int operator() (int val)
    {
        return val <0 ? -val: val;
    }
};


struct funcObejct
{
    int operator() (int val1,int val2,int val3)
    {
        return val1 ? val2:val3;
    }
};






//test code
int main()
{

  int i = -3;
  absInit  absTest;
  std::cout<<"abs of "<<i<<" is "<<absTest(i)<<std::endl;

  // test funcObject
  funcObejct fun;
  std::cout<<fun(-1,2,3)<<std::endl;
   std::cout<<fun(10,2,3)<<std::endl;
    std::cout<<fun(0,2,3)<<std::endl;


   return 0;




}





函数对象经常用作通用算法的实参,通过将算法中需要的Predicate 定义为函数对象可以获得更高的灵活性:


bool GT6(const std::string &s)
{
    return s.size() >6;
}



class GT_cls
{
    public:
      GT_cls(std::size_t val = 0):bound(val) {}
      bool operator() (const std::string & s) { return s.size() >= bound;}
    private:
      std::string::size_type bound;
};


//test code
int main()
{

    std::vector<std::string> words;
    std::string word;
    while(std::cin>>word)
    {
        words.push_back(word);
    }

    std::vector<std::string>::size_type wc = std::count_if(words.begin(),words.end(),GT6);
    std::cout<<wc<<std::endl;

    std::vector<std::string>::size_type wc1 = std::count_if(words.begin(),words.end(),GT_cls(6));
    std::cout<<wc1<<std::endl;

    std::vector<std::string>::size_type wc2 = std::count_if(words.begin(),words.end(),GT_cls(2));
    std::cout<<wc2<<std::endl;
    
    
    
    return 0;

}





标准库定义了一组算术,关系与逻辑运算的函数对象类,以及一组函数适配器,都是在functional 头文件中定义的;


具体请参考:http://en.cppreference.com/w/cpp/header/functional


在算犯中使用函数对象,用于覆盖算法使用的默认操作符;



标准库提供两种函数适配器:

1. binder,将一个操作数绑定给给定值而将二元函数对象转换为一元函数对象;

     bind1st:将给定值绑定到函数对象的第一个实参;

bind2nd:将给定值绑定到函数对象的第二个实参;

2. negator ,将谓词函数对象的真值求反;

    not1:将一元函数对象的真值求反;

    not2:将二元函数对象的真值求反;




//test code
int main()
{

    std::vector<int> ivec;
    ivec.reserve(1030);
    for(int i = 0 ; i <1030 ;++i)
    {
        ivec.push_back(i);
    }


    //find all value that is greater than 1024
    std::vector<int>::iterator result = std::find_if(ivec.begin() ,  ivec.end() , std::bind2nd(std::greater<int>() ,1024) );

    while(result != ivec.end())
    {
        std::cout<<*result<<std::endl;
        result = std::find_if( ++result ,  ivec.end() , std::bind2nd(std::greater<int>() ,1024) );
    }



    std::vector<std::string> svec;
    svec.push_back("hello world");
    svec.push_back("test");
    svec.push_back("huqijun");
    svec.push_back("pooh");

    //find all value that is not equal to "pooh"
    std::vector<std::string>::iterator ret = std::find_if(svec.begin(),svec.end(),std::bind2nd(std::not_equal_to<std::string>(),"pooh") );
    while(ret != svec.end())
    {
        std::cout<<*ret<<std::endl;
        ret = std::find_if(++ret,svec.end(),std::bind2nd(std::not_equal_to<std::string>(),"pooh") );
    }


    //double every value
    std::vector<int> ivec2;
    ivec2.reserve(12);
    for(int i = 0; i<12 ; ++i)
    {
        ivec2.push_back(i);
    }

    std::for_each(ivec2.begin(),ivec2.end(),std::bind2nd(std::multiplies<int>(),2) );

    for(std::vector<int>::iterator i = ivec2.begin() ;  i!= ivec2.end()  ; ++i)
    {
        std::cout<<*i<<std::endl;
    }
    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值