第 3 章 迭代器概念与traits编程技法

重载箭头运算符

        迭代器的功能类似指针,指针两个最重要的功能就是内容提领和成员访问。内容提领可以利用重载解引用运算符解决,成员访问运算符需要重载箭头运算符。重载箭头运算符永远都是用于成员访问的含义。如果类重载了箭头运算符,并且其结果本身也重载了箭头运算符,那么会调用其结果的成员运算符;如果结果是一个指针,会对其解引用并且访问某个我们指定的成员。

下面是一个测试例子:

#include <iostream>
using namespace std;

struct A
{
        const static int a=2;
};

class B
{
public:
        A* operator->() {cout<<"B::operator->()"<<endl;return &ba;}
private:
        A ba;
};

class C
{
public:
        B operator->() {cout<<"C::operator->()"<<endl;return cb;}
private:
        B cb;
};

int main()
{
        C c;///////////////输出结果:
        int r=c->a;////////C::operator->()
        cout<<r<<endl;/////B::operator->()
}                        //2

迭代器

        首先迭代器内部有多个typedef语句,这些语句定义了迭代器种类,底层对象型别。迭代器的种类,有输入迭代器,输出迭代器,前向迭代器,双向迭代器,随机访问存储器,迭代器通过容器内部元素组织方式来确定其所属种类,比如vector,其底层就是动态数组,那么其迭代器就具有随机访问功能,而对list迭代器,因为其底层是双向链表,那么只能递增或者递减的功能,由此可以看出不同容器的迭代器具有不同的功能,因此每种容器都具有自己特有的迭代器。迭代器的种类的作用是在算法中确定如何访问容器元素。

        迭代器有了底层对象的型别,比如第二章,在将空间的对象析构的时候,可以通过迭代器底层对象的型别来确定是否需要调用析构函数。书中有一句话这么说,设计适当的相应型别,是迭代器的责任,而设计适当的迭代器则是容器的责任,我是这么理解的,我们创建容器,仅仅只能通过迭代器来访问底层元素(不包括某些顺序容器重载[]运算符),那么对于底层元素的任何信息,迭代器都必须使得这些信息对我们可见,而迭代器的是如何去遍历容器,这一点只有容器自己知道,那么设计迭代器的责任就需要容器来完成了。而STL的算法是独立的,其可以通过迭代器来访问元素,只不过访问元素的方式可以通过迭代器的种类来确定,这里面在每个类中大量运用了typedef语句来定义类的信息。

type_traits头文件

        这个头文件很有意思。其内部有一个类模板__type_traits,这个类内部包括类的型别特性,包括第二章的trival_destructor这些属性,当我们自己定义一个类的时候,我们可以特化一个__type_traits类,其内部的typedef语句我们自己设计,这样就可以设计自己类的型别信息了。其内部对于标量型别分别特化属于自己的__type_traits类。

总结

        由于C++里面并没有能够识别类的型别信息的功能,当我们需要这些信息的时候可以设计模板,通过模板参数推到来确定型别,这是个很重要的模板编程技巧。

猜你喜欢

转载自blog.csdn.net/w1157984197/article/details/79775673