C++面向对象程序设计-Seventh Week

(1)面向对象编程(OOP)与泛型编程(GP)之间的区别:

OOP试图将datas与methods关联在一起,为此在OOP中,将数据与操作放置在同一个类中,同时设定了类之间的继承关系。

GP则是将datas与methods分离。例如sort没有被定义为类内的成员函数,而是将其归入STL的算法中,作为一个全局函数存在。算法和容器之间利用迭代器进行关联。

采用GP编码:

<1>Containers和Algorithms彼此之间不存在交叉,两者可以单独进行开发,只需要利用Iterator进行沟通即可。

<2>Algorithms可以通过Iterators确定其操作范围,并且可以通过Iterators取用Container中的元素。

在上述例子中,可以看出两个max函数一个使用了编译器自带的<操作,而另一个使用仿函数comp自定义比较规则。对于所有Algorithms,其中最终涉及元素本身的操作,无非就是比较大小。由于上述函数利用了模板,因此应当注意所传入的类型T应当能够支持进行相对应的比较操作,否则则需要对比较操作运算符进行重载。

对于操作符重载应该注意:并不是所有的操作符都能够被重载。重载之后的操作符函数可以被作为一个全局函数,也可以被作为一个成员函数。

(2)模板

<1>类模板:注意其关键字template。其中的T类型不确定,在模板被使用时确定其具体类型。

<2>函数模板:其关键字template。在使用时,编译器会对函数模板进行实参推导,确定模板中T的具体类型。

<3>成员模板

(3)模板的特化

特化可以被分为全特化与偏特化。

<1>一个被泛化的模板为:

template

struct A{…..}

经过全特化后为:

template<>struct A{…..}

template<>struct A{…..}

<2>偏特化也被称为局部特化。

template

class vector{......};

实施偏特化后:

template

class vector{......};

上述偏特化为个数的偏特化。

template

struct A{…..};

能够接受任意类型的type。将其进行范围的偏特化,使其只能够接受固定类型的type。

template

struct A{…..};

template

struct A{…..};

(4)分配器allocators

分配器所分配内存是使用operator new()和malloc()函数完成容器所需要的内存的分配。

通过上图可以看出,通过分配器所分配的内存比实际所需要的内存数量要大,其中包括cookie等额外所分配的控件。所需要分配的控件越小,则其所额外分配的内存在总体内存中所占用的比例越大。本周课堂上所比较的几种编译器只是以::operator new和::operator delete完成allocate()和deallocate(),没有任何特殊的设计.。

可以利用allocator()完成临时对象的创建。

int* p = allocator().allocate(512,(int*)0);

其中必须指定所分配的内存的大小。同时在进行内存释放时:

allocator().deallocate(p,512);

释放内存时必须同时给出所分配的内存数目。

在G4.9所附带的标准库中,有许多extention allocators(附加类型的分配器)。

其中__pool_alloc就是G2.9中的alloc。

(5)List

list容器是一种双向的链表,因此其节点除了存放数据之外,还存在一个向前的指针和一个向后的指针。

template

struct __list_node{

typedef void* void_pointer;

void_pointer    prev;

void_pointer     next;

T  data;

}

由此可知list容器的迭代器的结构如下:

template

struct __list_iterator{

typedef   T  value_type;

typedef   Ptr  pointer;

typedef  Ref  reference;

……

}

除了vector和array之外。其余容器的迭代器都应当是一个class,也就是一个智能指针。

迭代器的++++和----操作:

前++为:

self& operator++()

{

node= (link_type)((*node).next);

return *this;

}

后++为:

self operator++(int)

{

self tmp = *this;     //记录原值

++*this;                  //进行操作

return tmp;//返回原值

}

本次编程作业中要求打印中间元素:

Index = (ListData.size()) / 2;

for(iList = ListData.begin(); iList != ListData.end();++++iList)

{

----Index;

if(Index == 0)

{

cout<< "中间元素为:" << *iList << endl ;

break;

}

}

使用++++能够得到正确的节点值,而++得到的是正确节点的前一个节点值。

(6)Traits

iterator需要遵循的原则

std::rotate(__first,__middle,__last,std::iterator_category(__first));

在上例中,rotate()需要知道iterators的三个associated types。

iterators必须有能力回答algorithms的提问。这样的提问在C++标准库开发过程中设计了五种:category:种类;difference_type;距离;value_type:值类型;reference;pointer。

如果iterator不是一个class,也就是说此时iterator是一个原生指针,这时的iterator被称为退化的。

Iterator Traits用以分离class iterators和non—class iterators。

(7)容器vector

Vector容器的容积以二倍增长的形式增长。

Vector容器的迭代器就是一个原生指针。

(8)容器array

Array在C++11后,被添加至容器中。定义一个array必须指定其长度,一旦定义,array无法自动变更容积。

(9)forward_list容器

作者:游在路上的鱼

链接:http://www.jianshu.com/p/2ad200d9a018

來源:

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(C++面向对象程序设计-Seventh Week)