函数对象
函数对象:
通常我们可以将函数作为参数传入另一个参数,比如qsort中传递函数指针。
STL函数对象则是函数指针的一种抽象形式。
传递方式:
由于标准库函数中,函数指针的传递是按照值传递的;所以函数对象在函数之间的传递也是 值传递。
for_each示例:
template<class InputIterator, class Function>
Function
for_each(InputIterator first, InputIterator last, Function f);//按值传递past-by-value
函数对象示例:
class Dosomething :public unary_function<int, void>{
public:
void operator()(int x){};
};
int main()
{
typedef vector<int>::iterator IntIterator;
vector<int> di;
Dosomething d;//创建一个函数对象
//用类型参数dequeInerator和Dosomething&来调用for_each,这将强制d按照引用传递并返回
for_each<IntIterator, Dosomething&>(di.begin(), di.end(), d);
return 0;
}
合理设计:
因为函数对象是按照值传递的,所以需要注意一些问题:
- 函数对象应该尽可能的小, 减小拷贝时的花销
- 函数对象应该是单态的,否则值传递过程中会发生剥离(派生类对象 赋值到 基类对象上,仅仅保留基类部分)
但是没有继承的函数子类感觉很鸡肋
解决:
将函数子类中的 大量数据 和 多态放置到一个新的类中,然后函数对象中值保存新类的指针。
(通过新生类实现多态并减小了函数子类的负担)
template<typename T>
class BPFCImpl :public unary_function<T, void>{
private:
float a;//原来BPFC中的数据
int x;
virtual ~BPFCImpl();//多态类需要虚析构函数
virtual void operator()(const T& val)conat;
friend class BPFC<T>;//允许BPFC访问内部数据
};
//通过BPFCImpl的多态实现函数对象的多态
template<typename T>
class BPFC :public unary_function<T, void>{
private:
BPFCImpl<T> *pImpl;
public:
void operator()(const T& val)const
{
pImpl->operator()(val);
}
};
参考:
Effective STL