Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > 理解STL中的函数子,函数子类,和其用法
【标  题】:理解STL中的函数子,函数子类,和其用法
【关键字】:STL
【来  源】:http://blog.csdn.net/SpriteLW/archive/2006/12/07/1434024.aspx

理解STL中的函数子,函数子类,和其用法

Your Ad Here
首先要知道什么是函数子,什么是函数子类,与其和函数的区别。简单地说,函数子是一个对象,而函数子类是该对象的类,并且该类要实现operator();函数是在类之外的函数,例如:
struct MaxWeight:public binary_function<Widget,Widget,bool>
{
    
bool operator()(const Widget& lhs,const Widget &rhs)
    {
        
return lhs.m_weigth > rhs.m_weigth ;
    }
};
int Print(const Widget &w)
{
    printf(
"%d ",w.m_weigth);
    
return 0;
}
       类MaxWeight为函数子类,Print为函数。用class或struct因个人风格而定。
 
       设类Widget有属性weight,现要对它进行显示。有以下几种方法
#include <vector>
#include 
<iostream>
#include 
<functional>
#include 
<algorithm>

using namespace std;
class Widget
{
public:
    
int m_weight;
    
//成员函数
    int printWithClassMemberFunction()
    {
        cout
<<m_weight<<" ";
        
return 0;
    }
    
//内部函数子类
    struct PrintWithInnerClass:public unary_function<Widget,void>
    {
        
void operator()(const  Widget &w)
        {
            cout
<<w.m_weight<<" ";
        }
    };
};

//外部函数子类
struct PrintWithOuterClass:public unary_function<Widget,void>
{
    
void operator()(const  Widget &w)
    {
        cout
<<w.m_weight<<" ";
    }
};
//外部函数
int PrintWithOuterFunction(const Widget &w)
{
    cout
<<w.m_weight<<" ";
    
return 0;
}

int main(int argc, char* argv[])
{
    
const int MaxCount = 20;
    
//容器元素为非指针
    vector<Widget> vDataWithNonPoint;
    
forint i=0; i<MaxCount; i++)
    {
        Widget w;w.m_weight 
= rand() % MaxCount;
        vDataWithNonPoint.push_back(w);
    }
    cout
<<"PrintWithOuterFunction:"<<endl;
    for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),PrintWithOuterFunction);

    cout
<<endl<<"ptr_fun(PrintWithOuterFunction):"<<endl;
    for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),ptr_fun(PrintWithOuterFunction));

    cout
<<endl<<"mem_fun_ref(Widget::printWithClassMemberFunction)"<<endl;
    for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),mem_fun_ref(Widget::printWithClassMemberFunction));

    cout
<<endl<<"Widget::PrintWithInnerClass()"<<endl;
    for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),Widget::PrintWithInnerClass());

    cout
<<endl<<"PrintWithOuterClass()"<<endl;
    for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),PrintWithOuterClass());

    cout
<<endl;
    system(
"PAUSE");
    
return 0;
}
 
输出如下:
PrintWithOuterFunction:
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
ptr_fun(PrintWithOuterFunction):
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
mem_fun_ref(Widget::printWithClassMemberFunction)
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
Widget::PrintWithInnerClass()
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
PrintWithOuterClass()
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
 
       有以下几个问题要注意:
1、  对PrintWithOuterFunction 和 ptr_fun(PrintWithOuterFunction) 操作,似乎ptr_fun是多余的。准确地说是在特定情况下ptr_fun可有可无,当要用not2,bind1st时就必须加上ptr_fun,因为ptr_fun的作用是把OuterFunction转unary_function<Widget,void>类似的类型,其它的还有binary_function,那正是not2,bind1st等函数所需要的
2、  为什么printWithClassMemberFunction返回int?如果不加ptr_fun则返回void也可以,但如果加了ptr_fun则必需要返回一个类型,不知是不是vc的原因,void似乎不认void为类型
3、  对函数子类的用法(外部类或内部类),类型名后一定要加()。似乎是调用operator(),其实不是,它是创建了一个匿名对象,俗称“函数子”,所以for_each里调用的都是一个函数子。
4、  为什么我要注明“容器元素为非指针”?回答这个问题,我要对上述每个函数作一个讲解。
4.1 for_each(。。。。,PrintWithOuterFunction):
        for_each每次迭代都传给 函数PrintWithOuterFunction一个Widget,这正是PrintWithOuterFunction形参的类型
 
4.2 for_each(。。。。, mem_fun_ref(Widget::printWithClassMemberFunction)):
        for_each每次迭代都对容器中的一个元素 I 调用 I. printWithClassMemberFunction()。注意,因为容器元素类型为“非指针”,所以调用”.”方法,当容器元素类型为“指针”时,则要将mem_fun_ref改为mem_fun,在内部,它对每个容器元素I,调用I->printWithClassMemberFunction()。(如果printWithClassMemberFunction有参数呢?那就要调用bind方法了)
 
4.3 Widget::PrintWithInnerClass()和PrintWithOuterClass():
        For_each会对函数子进行操作,调用void operator()(const Widget &w),那么for_each怎么会知道要传一个Widget参数和返回void呢?那是因为函数子类继承自unary_function<Widget,void>的原因,其中<>中,第一个为参数类型,第二个为返回类型。
 
到目前为止,我们的“函数子”都是一个参数或无参数的,现在要看有两个参数的情况,那就是要为Widget排序:
 
#include <vector>
#include 
<iostream>
#include 
<functional>
#include 
<algorithm>

using namespace std;
class Widget
{
public:
    
int m_weight;
    
//成员函数
    bool operator<(const Widget& rhs)
    {
        
return this->m_weight<rhs.m_weight;
    }
    
//成员函数
    bool LessWeightWithMemberFunction(const Widget &rhs)
    {
        
return this->m_weight<rhs.m_weight;
    }
    
//内部类
    struct LessWeightWithInnerClass:public binary_function<Widget,Widget,bool>
    {
        
bool operator()(const Widget& lhs,const Widget& rhs) const
        {
            
return lhs.m_weight<rhs.m_weight;
        }
    };
};
//调用less<Widget>时内部调用operator<
bool operator<(const Widget& lhs,const Widget& rhs)
{
    
return lhs.m_weight<rhs.m_weight;
}

bool lessWeightWithOutFunction(const Widget& lhs,const Widget& rhs)
{
    
return lhs.m_weight<rhs.m_weight;
}
//外部函数子类
struct LessWeightWithOuterClass:public binary_function<Widget,Widget,bool>
{
    
bool operator()(const Widget& lhs,const Widget& rhs) const
    {
        
return lhs.m_weight<rhs.m_weight;
    }
};

//外部函数子类
struct PrintWithOuterClass:public unary_function<Widget,void>
{
    
void operator()(const  Widget &w)
    {
        cout
<<w.m_weight<<" ";
    }
};

int main(int argc, char* argv[])
{
    
const int MaxCount = 20;
    
//容器元素为非指针
    vector<Widget> vDataWithNonPoint;
    
forint i=0; i<MaxCount; i++)
    {
        Widget w;w.m_weight 
= rand() % MaxCount;
        vDataWithNonPoint.push_back(w);
    }
    
//默认调用类内部的operator<
    sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end());
    
//调用外部的bool operator<(const Widget& lhs,const Widget& rhs)
    sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),less<Widget>());
    
//调用类成员函数
    sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),mem_fun1_ref(Widget::LessWeightWithMemberFunction ));
    
//调用外部函数
    sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),lessWeightWithOutFunction);
    
//调用内部函数子类
    sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),Widget::LessWeightWithInnerClass());
    
//调用外部函数子类
    sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),LessWeightWithOuterClass());

    for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),PrintWithOuterClass());
    cout
<<endl;
    system(
"PAUSE");
    
return 0;
}
 
有以下几个问题要注意:
1、函数子类继承自binary_function<Widget,Widget,bool>,它表示要输入两个参数,并返回bool。
2、成员函数的“包装”由mem_fun_ref改为mem_fun1_ref
 
 
frexp ( )【C语言库函数源代码】:【上一篇】
递归函数的学习:【下一篇】
【相关文章】
  • std::string及iostream实现性能比较:stlport VS GNU libstdc++
  • 使用C++(STL)+Cgicc+OTL+prototype开发简易CGI留言本(2)
  • stl 容器(1)
  • stl 容器(2)
  • Castle ActiveRecord中ntext类型的映射
  • stl中的异常
  • STL容器的拷贝构造和赋值特性
  • 使用C++(STL)+Cgicc+OTL+prototype开发简易CGI留言本(1)
  • 如何读取MaxRequestLength的值----(.net2.0)
  • STL中mem_fun和mem_fun_ref的用法
  • 【随机文章】
  • Test King
  • C++Builder的多线程编程中一些体会
  • Ulead SmartSaver Pro 3.0秘籍点点通(十八)
  • 用powerdesigner11导出sql的问题
  • 使用Action创建一个JButton后,改变该按钮的名字可能会遇到意想不到的问题
  • C++ Builder 给窗体传递其他参数
  • 美白方法美白秘方如何美白皮肤美白全身美白的方法看康本美白全攻略
  • 龙拳
  • 模版页中引用文件路径的问题
  • Red Had 9 下NFS服务创建步骤
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.