`
aspnetwinform
  • 浏览: 91882 次
  • 性别: Icon_minigender_2
  • 来自: 武汉
社区版块
存档分类
最新评论

从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法

 
阅读更多

一、函数对象

1、函数对象(function object)也称为仿函数(functor)


2、一个行为类似函数的对象,它可以没有参数,也可以带有若干参数。


3、任何重载了调用运算符operator()的类的对象都满足函数对象的特征


4、函数对象可以把它称之为smart function。


5、STL中也定义了一些标准的函数对象,如果以功能划分,可以分为算术运算、关系运算、逻辑运算三大类。为了调用这些标准函数对象,需要包含头文件<functional>。


二、自定义函数对象

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br></nobr>
#include<iostream>
usingnamespacestd;
classCFunObj
{
public:
voidoperator()()
{
cout<<"hello,functionobject!"<<endl;
}
};
intmain()
{
CFunObjfo;
fo();
CFunObj()();
return0;
}

注意:CFunObj()(); 表示先构造一个匿名对象,再调用operator();


三、函数对象与容器


在这边举map 容器的例子,大家都知道map 在插入元素的时候会自动排序,默认是根据key 从小到大排序,看map 的定义:

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br></nobr>
//TEMPLATECLASSmap
template<class_Kty,
class_Ty,
class_Pr=less<_Kty>,
class_Alloc=allocator<pair<const_Kty,_Ty>>>
classmap
:public_Tree<_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>
{
//orderedred-blacktreeof{key,mapped}values,uniquekeys
};

假设现在我们这样使用 map< int, string > mapTest; 那么默认的第三个参数 _Pr = less<int>,再者,map 继承的其中一个类


_Tmap_traits 中有个成员:


_Pr comp;// the comparator predicate for keys


跟踪进insert 函数,其中有这样一句:


if (_DEBUG_LT_PRED(this->comp,_Key(_Where._Mynode()), this->_Kfn(_Val)))


已知#define _DEBUG_LT_PRED(pred, x, y) pred(x, y) 很明显地,comp 在这里当作函数对象使用,传入两个参数,回头看less 类的


模板实现:

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br></nobr>
//TEMPLATESTRUCTless
template<class_Ty>
structless
:publicbinary_function<_Ty,_Ty,bool>
{
//functorforoperator<
booloperator()(const_Ty&_Left,const_Ty&_Right)const
{
//applyoperator<tooperands
return(_Left<_Right);
}
};

即实现了operator() 函数,左操作数小于右操作数时返回为真。


我们也可以在定义的时候传递第三个参数,如map< int, string, greater<int> > mapTest; 则插入时按key 值从大到小排序(less,


greater 都是STL内置的类,里面实现了operator() 函数),甚至也可以自己实现一个类传递进去,如下面例程所示:

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br></nobr>
#include<map>
#include<string>
#include<iostream>

usingnamespacestd;

structMyGreater
{
booloperator()(intleft,intright)
{
returnleft>right;
}
};

intmain(void)
{
map<int,string,/*greater<int>*/MyGreater>mapTest;
mapTest.insert(map<int,string>::value_type(1,"aaaa"));
mapTest.insert(map<int,string>::value_type(3,"cccc"));
mapTest.insert(map<int,string>::value_type(2,"bbbb"));


for(map<int,string,/*greater<int>*/MyGreater>::const_iteratorit=mapTest.begin();it!=mapTest.end();++it)
{
cout<<it->first<<""<<it->second<<endl;
}

return0;
}

输出为:

3 cccc

2 bbbb

1 aaaa


MyGreater 类并不是以模板实现,只是比较key 值为int 类型的大小。


四、函数对象与算法

在STL一些算法中可以传入函数指针,实现自定义比较逻辑或者计算,同样地这些函数也可以使用函数对象来代替,直接看例程再稍

作分析:

C++ Code
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br> 44<br> 45<br> 46<br> 47<br> 48<br> 49<br> 50<br> 51<br> 52<br> 53<br> 54<br> 55<br> 56<br> 57<br> 58<br> 59<br> 60<br> 61<br> 62<br> 63<br> 64<br> 65<br> 66<br> 67<br> 68<br> 69<br> 70<br> 71<br> 72<br> 73<br> 74<br> 75<br> 76<br> 77<br> 78<br> 79<br> 80<br> 81<br> 82<br></nobr>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>

usingnamespacestd;

voidPrintFun(intn)
{
cout<<n<<'';
}

voidAdd3(int&n)
{
n+=3;
}

classPrintObj
{
public:
voidoperator()(intn)
{
cout<<n<<'';
}
};

classAddObj
{
public:
AddObj(intnumber):number_(number)
{

}
voidoperator()(int&n)
{
n+=number_;
}

private:
intnumber_;
};

classGreaterObj
{
public:
GreaterObj(intnumber):number_(number)
{

}
booloperator()(intn)
{
returnn>number_;
}
private:
intnumber_;
};


intmain(void)
{
inta[]={1,2,3,4,5};
vector<int>v(a,a+5);

/*for_each(v.begin(),v.end(),PrintFun);
cout<<endl;*/


for_each(v.begin(),v.end(),PrintObj());
cout<<endl;

/*for_each(v.begin(),v.end(),Add3);
for_each(v.begin(),v.end(),PrintFun);
cout<<endl;*/


for_each(v.begin(),v.end(),AddObj(5));
for_each(v.begin(),v.end(),PrintFun);
cout<<endl;


cout<<count_if(a,a+5,GreaterObj(3))<<endl;//计算大于3的元素个数

return0;
}

输出为:

1 2 3 4 5

6 7 8 9 10

2


回顾for_each 的源码,其中有这样一句:_Func(*_ChkFirst); 也就是将遍历得到的元素当作参数传入函数。


上面程序使用了函数对象,实际上可以这样理解PrintObj()(*_ChkFirst); 即PrintObj() 是一个匿名的函数对象,传入参


数,调用了operator() 函数进行打印输出。使用函数对象的好处是比较灵活,比如直接使用函数Add3,那么只能将元素加3,而


使用函数对象Addobj(x), 想让元素加上多少就传递给Addobj类,构造一个对象即可,因为它可以保存一种状态(类成员)。


count_if 中的 GreaterObj(3) 就类似了,将遍历的元素当作参数传递给operator(), 即若元素比3大则返回为真。



五、STL内置的函数对象类



参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范



分享到:
评论

相关推荐

    从零开始学C++

    第11章至第13章,可能会涉及模板和STL(Standard Template Library,标准模板库),包括函数模板、类模板、容器(如vector、list、set)、迭代器和算法。模板是C++的泛型编程工具,STL则是提高代码效率和可读性的...

    从零开始学c++(ppt)

    《从零开始学C++》是一份专为初学者设计的教学资料,旨在引导学习者逐步掌握C++编程语言。这份教程包含丰富的基础知识讲解,搭配教案和源代码,使得学习过程更具实践性和互动性。 首先,从C++的基础部分开始,学习...

    c++(程序设计)从零开始

    4. **标准模板库(STL)**:STL是C++的一个强大工具,包含容器(如vector、list、map)、算法(如排序、查找)和迭代器等,大大提高了代码的可读性和效率。 5. **模板**:C++的模板功能允许创建泛型代码,可以用于...

    C++从零开始 C++从零开始

    作为一个从零开始的学习者,理解C++的基础知识至关重要。以下是一些关于C++的核心概念和知识点: 1. **基础语法**:C++基于C语言,但扩展了面向对象特性。学习C++首先需要掌握基本的语法结构,包括变量声明、数据...

    《易学c++》从零开始学c++的最好入门教材。

    书中会介绍如何编写和使用函数模板、类模板以及STL(Standard Template Library)中的容器、算法和迭代器。 4. **异常处理**:C++提供了异常处理机制,用于处理程序运行时可能出现的错误。通过try、catch和throw...

    从零开始学C++,C++从零开始

    总的来说,"从零开始学C++"意味着要从基础语法开始,逐步深入到高级特性,包括面向过程编程、面向对象编程、模板、异常处理、STL的使用以及设计模式的应用。通过系统学习和大量实践,你可以逐渐成长为一名熟练的C++...

    C++ STL编程轻松入门

    总的来说,“C++ STL编程轻松入门”文档将详细阐述这些概念,并通过实例演示如何在实际项目中应用STL,帮助读者从零开始掌握这一强大的工具集。通过学习,你不仅能提升C++编程的效率,还能理解面向对象和泛型编程的...

    C++从零开始

    【C++从零开始】 C++是一种通用的编程语言,由Bjarne Stroustrup于1983年在C语言的基础上发展而来,它既具有面向过程的特性,也支持面向对象的编程范式,同时还引入了泛型编程和模板等高级特性。C++的设计目标是...

    c++从零开始学(有关C++学习的资料)

    提供的"从零开始学"资源可能涵盖了以上这些主题,通过阅读电子书和练习示例代码,初学者可以逐步构建自己的C++知识体系。记得,学习编程是一个持续的过程,不断练习和探索新的技术是提高技能的最佳方式。祝你在C++的...

    effective(more effective) c++ C++ primer 高质量C++编程指南 深度探索C++对象模型 effective STL合集

    5. **《Effective STL》**:Scott Meyers再次展示了他在C++模板库(STL)方面的深厚功底,提供了50条关于如何有效使用容器、迭代器、算法和函数对象的建议。这本书有助于提升程序员对STL的理解,使其能够更好地利用...

    从零开始学Visual C++ 源程序

    《从零开始学Visual C++》是一本针对初学者的编程教材,由刘雪洁和刘永纯等作者编著,旨在帮助读者从基础开始掌握使用Visual C++进行程序开发的技术。这本书涵盖了一系列Visual C++的基础知识和实践技巧,通过学习,...

    C++学习教程从零开始(八)-C++样例一共20页.pd

    【标题】"C++学习教程从零开始(八)-C++样例一共20页.pdf" 提供的是一份C++编程语言的学习教程,针对初学者,旨在帮助他们掌握C++的基础知识并理解编程实践。这个教程包含了20页的实例代码和解释,涵盖了C++的关键...

    C++入门学习,从零开始,图片讲解

    在本资源中,"C++入门学习,从零开始,图片讲解"是一个为初学者设计的C++教程,旨在通过直观的图片形式帮助理解复杂的编程概念。教程的创建者自称"小菜鸡",他分享了自己的学习过程和积累的经验,相信这将对其他初学...

    c++语言STL - 概要及容器部分讲解(大连理工资深教授)

    - **减少重复工作**:许多常见的编程任务如排序、查找等都可以通过STL提供的现成解决方案来完成,无需程序员从零开始实现。 - **提高代码质量**:STL组件经过长时间的测试和完善,相比个人或小团队开发的数据结构和...

    c++ 入门 教程 由浅入深学习c++

    本教程旨在帮助你从零开始,逐步深入地学习C++。 首先,"C++ Primer"是一本经典的C++入门书籍,它覆盖了C++的基础语法、面向对象编程以及更高级的主题。这本书会引导你理解变量、数据类型、运算符、控制结构(如if...

    零起点学通C++光盘镜像。

    根据提供的文件信息,我们可以推断出这是...综上所述,这套“零起点学通C++”的教学资源旨在为初学者提供全面而系统的C++学习指南,涵盖了从基础到高级的多个层面,对于希望从零开始学习C++的人来说是一个很好的起点。

    C++ STL应用说明

    STL的出现使得程序员可以使用预定义的高质量组件来处理数据,而无需从零开始编写底层代码。 STL主要由以下几个核心组件构成: 1. 容器(Container):容器是用来存储和组织数据的类。STL提供了多种类型的容器,如...

    c与c++标准类库及函数.zip_C C++ 函数库_C++_C/C++标准库 chm_C标准库

    这些函数库构成了C语言的基础,为开发者提供了许多便利的操作,无需从零开始编写底层代码。 C++标准库则更为丰富,它不仅包含了C库的所有功能,还增加了许多面向对象编程的元素,如STL(Standard Template Library...

    零基础学C++ppt

    首先,从【第2章 开始C++之旅.ppt】开始,这章节会介绍C++的历史背景,以及它与C语言的关系,让学习者对C++有一个宏观的认识。同时,会讲解C++的基本语法,包括变量声明、数据类型、运算符、流程控制语句(如if-else...

    c++函数库_的_

    C++函数库是C++编程语言中不可或缺的一部分,它提供了大量的预定义函数和类,使得开发者可以更加高效地编写程序,而无需从零开始构建所有基础功能。C++标准库,也称为C++ Standard Template Library (STL),是C++中...

Global site tag (gtag.js) - Google Analytics