Effective STL学习笔记-条款38

来源:互联网 发布:网络机顶盒链接显示器 编辑:程序博客网 时间:2024/06/14 08:27

把仿函数类设计为用于值传递

仿函数大家都应该知道,看一下for_each的函数声明:

template<class InputIterator,class Function>Function // 注意值返回for_each(InputIterator first,InputIterator last,Function f); // 注意值传递

但是书写仿函数有一点小约定:

  • 你的函数对象应该很小。否则它们的拷贝会很昂贵。
  • 你的函数对象必须单态(也就是,非多态)——它们不能用虚函数。那是因为派生类对象以值传递代入基类类型的参数会造成切割问题:在拷贝时,它们的派生部分被删除。

当然效率很重要,避免切割问题也是,但不是所有的仿函数都是小的、单态的。函数对象比真的函数优越的的原因之一是仿函数可以包含你需要的所有状态。有些函数对象自然会很重,保持传这样的仿函数给STL算法和传它们的函数版本一样容易是很重要的。

禁止多态仿函数是不切实际的。C++支持继承层次和动态绑定,这些特性在设计仿函数类和其他东西的时候一样有用。

例如,你的仿函数有很大的数据,这时你的仿函数类可能需要小小的设计一下:

template<typename T>class Opt;  //声明template<typename T>class Data{    //大量数据private:    void operator()(const T& val) const {}    friend class Opt<T>;};template<typename T>class Opt{public:    void operator()(const T& val) const    {        m_pImpl->operator()(val);    }private:    Data<T> *m_pImpl;};int main(){    vector<int> iv;    std::for_each(iv.begin(), iv.end(), Opt<int>());    return 0;}

这里只给出大的结构,细节并没有补充完全,例如:使用这种技术的仿函数类必须支持合理方式的拷贝,也可以使用智能指针实现这个方案。
上述方法也称为“Bridge模式”或者“Pimpl惯用法”。

原创粉丝点击