GeekBand C++ STL与泛型编程 第五周笔记

  第五周讲到了标准模板库STL,看了下第六周的内容,容器被分成上下,分两周来说。因为笔记内容多为基础概念整理,所以将容器并入标准模板库概念里一起说明。这一周着重整理标准模板库和泛型编程。引用内容来源百度百科和维基百科。不知道CSDN的表格是怎么回事,编辑的时候还是有边框的,但使用之后就丢失边框。编辑了好几次,这次干脆直接截图改图片了。

  标准模板库(英文:Standard Template Library,缩写:STL),是一个C++软件库,也是C++标准程序库的一部分。其中包含4个组件,分别为算法、容器、函数、迭代器。模板是C++程序设计语言中的一个重要特征,而标准模板库正是基于此特征。标准模板库使得C++编程语言在有了同Java一样强大的类库的同时,保有了更大的可扩展性。

  标准模板库是由Alexander Stepanov创造于1979年前后,这也正是创造了C++的年代。虽然David R. Musser于1971年开始即在计算机几何领域发展并倡导写泛型程序设计观念,但早期并没有任何程式志愿泛型程序设计。第一个志愿泛型概念的语言就是Ada。到了C++模板概念,Stepanov参加了许多有关的研讨会,与C++之父Bjarne讨论模板的设计细节。如:Stepanov认为C++的函数模板应该像Ada一样,在声明其函数原型后,应该显示的声明一个函数模板之实例;Bjarne则认为可以透过C++的重载功能来表达。两人的函数模板如下:

<span style="font-size:14px;">//Stepanov设想的函数模板
   in *.hpp
   template<class T>
   T square(T x) { return x*x; }
 
   in *.cpp
   double square(double);
   cout << square(3.3);
   int square(int);
   cout << square(3);</span>
<span style="font-size:14px;">//Bjarne设想的函数模板
   in *.hpp
   template<class T>
   T square(T x) { return x*x; }
 
   in *.cpp
   cout << square(3.3);
   cout << square(3);</span>
  几经辩论,Stepanov非常认同Bjarne的做法。事实上,C++的模板本身就是一套的巨集语言,巨集语言的最大特色位:所有工作在编译时期就已完成。

  容器:在实际的开发过程中,数据结构本身的重要性不会逊于操作于数据结构的算法的重要性,当程序中存在着对时间要求很高的部分时,数据结构的选择就显得更加重要。经典的数据结构数量有限,所以常常重复着一些为了实现向量、链表等结构而编写的代码,这些代码都十分相似,只是为了适应不同数据的变化而在细节上有所出入。STL容器供了这样的方便,它允许重复利用已有的实现构造特定类型下的数据结构,通过设置一些模板类,STL容器对最常用的数据结构提供了支持,这些模板的参数允许指定容器中元素的数据类型,可以将许多重复而乏味的工作简化。标准模板库包含了序列容器(sequence containers)和关联容器(associative containers)。




  泛型编程:泛型程序设计是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时(instantiate)作为参数指明这些类型。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。Ada, Delphi, Eiffel, Java, C#, F#, Swift, and Visual Basic .NET称之为泛型(generics);ML, Scala and Haskell称之为参数多态(parametric polymorphism);C++与D称之为模板。具有广泛影响的1994年版的《Design Patterns》一书称之为参数化类型(parameterized type)。

  泛型的定义主要有以下两种:1.在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个别对象。2.在程序编码中一些包含参数的类。其参数可以代表类或对象等等。不论使用哪个定义,泛型的参数在真正使用泛型时都必须作出指明。一些强类型程序语言支持泛型,其主要目的是加强类型安全,及减少类转换的次数,但一些支持泛型程序语言只能达到部分目的。

  泛型编程伪代码例:

<span style="font-size:14px;">类例泛类<T> {
  值 : T

  设置值(新值 : T) {
    值 := 新值
  }

  获取值() : T {
    返回 值
  }
}

例方法1() {
  例物件 : 例泛类<整数型>
  例物件 := 新 例泛类<整数型>()
  例物件.设置值(5)
  输出整数(例对象.获取值())
}

例方法2() {
  例物件 : 例泛-{}-类<浮点数型>
  例物件 := 新 例泛类<浮点数型>()
  例物件.设置值(5.5)
  输出浮点数(例对象.获取值())
}</span>
  在这例子中,例泛类是一个泛型,而T是一个类型参数。在例泛类中没指名T的实际类型,只有例方法1()和例方法2()在使用例泛类时才加以指名。

  C++的泛型(模板):C++ 泛型的参数可以代表类或个别对象。在一般意义上,C++ 缺乏对泛型的类型参数进行直接约束的手段,但可利用 SFINAE(模板代换失败非错误,指在模板实例化过程中的错误仅意味此次代换失败,并不一定产生编译错误)规则及 C++11 的 static_assert 等实现相似功能。

<span style="font-size:14px;">#include <type_traits>

class B{
...
};
class D: public B{
...
};
template<typename T>
void SFINAE(const std::enable_if_t<std::is_base_of<B, T>::value, T> &t);
template<typename T>
void STATIC_ASSERT(const T &t){
    static_assert(std::is_pod<T>::value, "Use with POD types only!");
}</span>

  如上所示,std::enable_if(std::enable_if_t<boolean, Type> 是 std::enable_if<boolean, Type>::type 的缩写)利用 SFINAE 规则来实现模板类型参数约束的手段之一。其实现方式是若布尔判断为假,则把类型设为 void,而这将导致 const void & 这种不合法的类型出现,从而禁止这种类型参数的使用。







  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值