本部分包括OOP和GP的区别、阅读源码之前的必要基础等等。
一、OOP(Object-Oriented programming)与GP(Generic Programming)
1. OOP企图将datas和methods关联在一起
比如标准库中的list:
template <class T,
class Alloc = alloc>
class list{
......
void sort();
};
我们看到list定义了一个自己的成员函数,那么为什么list不能使用::sort()进行排序呢,我们先来看一下::sort()的源码:
template <class RandomAccessIterator>
inline void sort(RandomAccessIterator first, RandomAccessIterator last){
if(first != last){
__introsort_loop(first, last, value_type(first), __lg(last - first) * 2);
__final_insertion_sort(first, last);
}
}
template <class RandomAccessIterator, class T, class Size>
void __introsort_loop(RandomAccessIterator first,
RandomAccessIterator last,
T*,
Size depth_limit){
......
RandomAccessIterator cut = __unguarded_partition
(first, last, T(__median(*first, *(first + (last - first)/2), *(last - 1))));
......
}
我们发现::sort()支持的迭代器是随机访问迭代器,随机访问迭代器除了可以递增递减之外,还支持类似c.begin() + k的操作,而list中的迭代器不是随机访问迭代器,所以也就不提供这个操作。这样设计是合理的,因为list是链表,无法在线性时间内得到递增或递减k次的结果。
2. GP是将datas和methods分开来
采用GP:(1)Containers和Algorithms可以分别“闭门造车”,其间以iterator通信即可。(2)Algorithms通过iterators确定操作范围,并通过iterators取用Container的元素。
比如说vector和deque都提供随机访问迭代器,所以可以使用::sort()进行排序,体现了GP的设计思想。
template <class T,
class Alloc = alloc>
class vector{
......
};
template <class T,
class Alloc = alloc,
size_t BufSiz = 0>
class deque{
......
};
::sort()有两个版本:
template <typename _RandomAccessIterator>
inline void
sort(_RandomAccessIterator __first,
_RandomAccessIterator __last)
{
......
}
template <typename _RandomAccessIterator,
typename _Compare>
inline void
sort(_RandomAccessIterator __first,
_RandomAccessIterator __last,
_Compare __comp)
{
......
}
二、阅读C++标准库源码的必要基础
1. 操作符重载
这张图总结得很好。注意操作符重载既可以是成员函数,也可以是全局函数
但是不理解最后一栏,对象后面的一元操作符为啥非要有一个参数?(这个参数没有任何意义,只是为了区分前置和后置版本)
看一个例子:
template <class T, class Ref, class Ptr>
struct __list_iterator{
typedef __list_iterator<T, Ref, Ptr> self;
typedef bidirectional_iterator_tag iterator_catagory;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef __list_node<T>* link_type;
typedef ptrdiff_t difference_type;
link_type node;
reference operator*() const { return (*node).data; }
pointer operator->() const { return &(operator*()); }
self& operator++() { node = (link_type)((*node).next); return *this; }
self operator++(int) { self tmp = *this; ++*this; return tmp; }
};
2. 模板
介绍了类模板,函数模板,成员模板,模板特化,模板偏特化等的概念,这些以前课程都提过,这里就不细总结了。只介绍一个偏特化的例子:
(1) 个数上的偏
//泛化
template <class T,
class Alloc = alloc>
class vector
{
......
};
//个数上的偏特化
template <class Alloc>
class vector<bool, Alloc>
{
......
};
(2) 范围上的偏
//泛化
template <class Iterator>
struct iterator_traits{
typedef typename Iterator::iterator_catagory iterator_catagory;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};
//partial specialization for regular pointers
template <class T>
struct iterator_traits<T*>{
typedef random_access_iterator_tag iterator_catagory;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
//partial specialization for regular const pointers
template <class T>
struct iterator_traits<const T*>{
typedef random_access_iterator_tag iterator_catagory;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};