1.1 知识点
- 函数对象概述
- 预定义函数对象
- 辅助函数对象
- 适配器
- 函数对象使用方法
1.2 实验环境
- g++
- ubuntu 16.04
1.3 代码获取
可以通过以下链接获取本课程的源码内容,本次实验内容主要包含在文件Functional.h
。
//获取代码
wget http://labfile.oss.aliyuncs.com/courses/1166/mySTL.zip
//解压文件到Code目录
unzip -q mySTL.zip -d ./Code/
二、函数对象概述
函数对象是重载函数调用操作符的类的对象。即函数对象是行为类似函数的对象,又称仿函数,是一个能被当做普通函数来调用的对象。
函数对象与函数指针相比,有两个优点:第一是编译器可以内联执行函数对象的调用;第二是函数对象内部可以保持状态。
STL 中的众多算法,非常依赖于函数对象处理容器的元素。所以 STL 预定义了许多函数对象、谓词和适配器。
三、预定义和辅助函数对象
我们可以在 Functional.h 中预定义一些函数对象,以方便在以后的实验中直接调用。
首先在 include 目录下创建 Functional.h。
unary_function: 作为一元函数对象的基类,只定义了参数和返回值的类型
template<class T>
struct unary_function {
typedef T argumant_type;
typedef T result_type;
};
binary_function:作为二元函数基类,只定义了参数和返回值的类型
template<class T>
struct binary_function {
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
};
less:用于返回较小值
template<class T>
struct less{
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
result_type operator()(const first_argument_type& x, const second_argument_type& y){
return x < y;
}
};
equal_to: 判断是否相等
template<class T>
struct equal_to{
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
result_type operator()(const first_argument_type& x, const second_argument_type& y){
return x == y;
}
};
identity: 验证同一性
template <class T>
struct identity : public unary_function<T> {
const T& operator()(const T& x) const {return x;} //函数调用操作符
};
select1st: 返回键值,在 map 中会用到
template <class T>
struct select1st : public unary_function<T, typename T::first_type> {
const typename T::first_type& operator()(const T& x) const {return x.first;}
四、适配器
函数对象适配器本质上任然是一个函数;函数对象适配器提供了对函数对象或者普通函数的操作,使其能够根据我们的需求来修改函数对象或者普通函数的功能。
使用函数对象适配器的步骤:
(1)首先让自定义的函数对象 public 继承一个父类。这里有两个选择:binary_function 和 unary_function。如果有两个参数选择前者。
(2)定义一个函数对象作为参数传入函数对象适配器。常见的函数对象适配器有:
绑定适配器 bind1st bind2nd (bind1st 绑定第一个参数, bind2nd 绑定第二个参数)
取反适配器 not1 not2 (not1 作用于一元函数对象,not2 作用于二元函数对象)
普通函数适配器 ptr_fun
作用于类中方法的适配器 mem_fun mem_fun_ref
(3)加 const
五、实例测试
我们在上面讲了预定义函数对象和适配器,在下面我们就来演示预定义函数和适配器的搭配。我们在 Test
文件夹下建立 functionaltest.cpp
,在这里需要用到 vector 容器来测试,关于Vector
容器的内容,我们将在后面的实验中给大家讲解,这里我们直接使用 Vector.h
的内容。该文件可以通过下载课程源码找到。
#include <iostream>
#include "Vector.h"
#include "Functional.h"
using namespace std;
class compare:public binary_function<int,int,bool>{//用于接收两个参数
public:
bool operator()(int i, int num) const {
return i > num;
}
};
class comparetonum:public unary_function<int,bool>{//用于接收一个参数
public:
bool operator()(int i) const {
return i > 5;
}
};
void print(int i,int j)//普通函数对象
{
if (i > j){
cout << i << " ";
}
}
int main(){
mySTL::vector <int> vec;
for (int i = 0; i < 10; i++)
{
vec.push_back(i + 1);
}
mySTL::vector<int>::iterator it = find_if(vec.begin(), vec.end(), bind2nd(compare(),6));//找出大于6的第一个数
if (it == vec.end())
{
cout << "cannot find the number!" << endl;
}
else
{
cout << "find num: " << *it << endl;
}
mySTL::vector<int>::iterator rit = find_if(vec.begin(), vec.end(), not1(comparetonum())); //取反适配器的用法,找出小于5的第一个数
if (rit == vec.end())
{
cout << "cannot find the number!" << endl;
}
else
{
cout << "find num: " << *rit << endl;
}
mySTL::vector<int> vec1;
for (int i = 0; i < 10; i++)
{
vec1.push_back(i);
}
cout<<"The num larger than 5: ";
mySTL::for_each(vec1.begin(), vec1.end(), bind2nd(ptr_fun(print),5)); //使用ptr_fun将普通函数转换为函数对象,然后给函数对象绑定参数。
cout << endl;
return 0;
}
执行命令:
g++ functionaltest.cpp -std=c++11 -o functionaltest -I ../include
网友评论