Skip to content

Latest commit

 

History

History
164 lines (133 loc) · 4.61 KB

45 配接器.md

File metadata and controls

164 lines (133 loc) · 4.61 KB

配接器

前言

本节分析STL组件之一的配接器, 配接器就像转接口一样, 将一个对class封装变成了另外一个功能的class, 这在前面分析容器的时候遇到过, 比如: map, set等, 都是修改底层接口形成另外一个功能的class.

配接器可以应用于 : 仿函数, 迭代器, 容器.

关于配接器应用于容器前面都分析过了, 接下来就分析部分应用于仿函数和迭代器的配接器吧.

应用于迭代器

STL实现了很多应用于迭代器上的配接器, 比如 : reverse iterators,iostream iterators等, 这里就选择前两个进行分析

reverse iterators

template <class Iterator>
class reverse_iterator
{
protected:
  Iterator current;
public:
  // 反向迭代器的5种相应型别和正向的正向迭代器相同
  typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
  typedef typename iterator_traits<Iterator>::value_type value_type;
  typedef typename iterator_traits<Iterator>::difference_type difference_type;
  typedef typename iterator_traits<Iterator>::pointer pointer;
  typedef typename iterator_traits<Iterator>::reference reference;

  // 正向迭代器
  typedef Iterator iterator_type;
  // 反向迭代器
  typedef reverse_iterator<Iterator> self;

public:
  // 构造函数
  reverse_iterator() {}
  // 将反向迭代器与某种迭代器联系起来
  explicit reverse_iterator(iterator_type x) : current(x) {}
  reverse_iterator(const self& x) : current(x.current) {}

  // 返回正向迭代器      
  iterator_type base() const { return current; }
  // 反向迭代器取值时,先将正向迭代器后退一位,再取值
  reference operator*() const {
    Iterator tmp = current;
    return *--tmp;
  }
  // 反转后end变成了begin. begin变成了end
  // 注意一点就是end是指向最后一个元素的后一个位置
  self& operator++() {
    --current;
    return *this;
  }
  self operator++(int) {
    self tmp = *this;
    --current;
    return tmp;
  }
  self& operator--() {
    ++current;
    return *this;
  }
  self operator--(int) {
    self tmp = *this;
    ++current;
    return tmp;
  }

  // 前进和后退方向相反
  self operator+(difference_type n) const {
    return self(current - n);
  }
  self& operator+=(difference_type n) {
    current -= n;
    return *this;
  }
  self operator-(difference_type n) const {
    return self(current + n);
  }
  self& operator-=(difference_type n) {
    current += n;
    return *this;
  }
  reference operator[](difference_type n) const { return *(*this + n); }  
};

iostream iterators

template <class T, class Distance = ptrdiff_t> 
class istream_iterator {
	// 定义友元
  friend bool
    operator== __STL_NULL_TMPL_ARGS (const istream_iterator<T, Distance>& x,
        const istream_iterator<T, Distance>& y);
protected:
  istream* stream;	// 定义istream指针
  T value;
  bool end_marker;
  // 执行读
  void read() {
    end_marker = (*stream) ? true : false;
    // 当有数据等待就进行读操作
    if (end_marker) *stream >> value;
    // 当读取到不符合型别或者eof时返回false, 不再读取
    end_marker = (*stream) ? true : false;
  }
public:
	// 类型定义, 满足traits编程
  typedef input_iterator_tag iterator_category;
  typedef T                  value_type;
  typedef Distance           difference_type;
  typedef const T*           pointer;
  typedef const T&           reference;

  istream_iterator() : stream(&cin), end_marker(false) {}	// 默认传入cin指针
  istream_iterator(istream& s) : stream(&s) { read(); }
  reference operator*() const { return value; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
  pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
	// 这里迭代器++表示将要读取到下一个数据
  istream_iterator<T, Distance>& operator++() { 
    read(); 
    return *this;
  }
  istream_iterator<T, Distance> operator++(int)  {
    istream_iterator<T, Distance> tmp = *this;
    read();
    return tmp;
  }
};

应用于仿函数

要实现仿函数可配接就需要继承unary_functionbinary_function.

上一节仿函数所分析的"函数"都可用于配接.

template <class Operation, class T>
inline binder1st<Operation> bind1st(const Operation& op, const T& x) {
  typedef typename Operation::first_argument_type arg1_type;
  return binder1st<Operation>(op, arg1_type(x));
}

总结

本节对STL的配接器的部分函数进行了分析, stl_function.hstl_iterator.h文件里面还有很多函数, 有兴趣可以好好看看, 这里也只是简单的分析. 源码面前没有秘密.