概述
● C++模板和泛型编程简介
● 容器和容器接口的函数
C++模板简介
● C++泛型编程的形式
● 可以使函数和类不依赖具体类型,
○ 类模板
○ 函数模板
● 模板实例化
○ 模板声明并没定义函数或类,只是提供了一个函数和类的语法框架
○ 实例化:构造函数和类的过程
○ 显式实例化:在实例化是显示指明类型
○ 隐式实例化:由编译器推断
函数模板
● 什么是函数模板
○ 参数化的一族函数
○ 函数模板定义
template <typename T>
T max (const T& a, const T& b)
{
return (a>b)?a:b;
}
○ typename可以用class代替
○ 参数推导
■ 模板参数由传递给模板函数的实参决定
■ 不允许自动类型转换,每个T必须严格匹配:max(1,2.0)是错误的
● 正确方案
● max(static_cast<double>(1), 2.0)
● max<double>(1, 2.0)
○ 函数模板重载
■ 函数模板可以被重载
■ 非模板函数可以和同名的模板函数共存
■ 编译器通过参数推导决定调用哪个重载
C++类模板
● 类模板实参可以是某一类型或常量(仅限int或enum)
类模板
● 类模板声明
○ 拷贝构造函数和operator=的定义的写法
○ 类模板的实现
○ 类模板的使用
■ 注意Stack的Stack的写法:Stack<Strack<int>空格> intStackStack;
○ 类模板的特化和偏特化
■ 允许对类模板的某些参数类型对特化
■ 目的:特殊处理某些类型
template <> class Stack <std::wstring>
{
....
};
拷贝构造函数和operator=的类模板
操作符重载
● 大多数内置操作符支持重载
● 不可以定义新的操作符
● 不能重载内置类型的操作符
● 操作符重载的两种形式
○ 非静态成员函数
○ 静态全局函数
● 注意
○ 操作符重载不能带默认参数值
○ 除了operator=,其他操作符重载均可以被子类继承
泛型编程
● 关联特性(Traits)
○ “traits是服务于泛型编程的,其目的是让模板更加通用,同时把一些细节向普通的模板用户隐藏起来。当用不同的类型去实例化一个模板时,不可避免有些类型会存在一些与众不同的属性,若考虑这些特性的话,可能会导致形成的模板不够“泛型”或是过于繁琐,而traits的作用是把这些特殊属性隐藏起来,从而实现让模板更加通用。”
○ 课程中举得的例子:将不同类型T的sigma函数的返回值通过trait技术关联到另外的类型,隐藏了类型转换的细节,使用者不用关心细节,足够“泛型”。
● 迭代器
○ 泛化的指针
○ 容器和算法间的接口
○ 有了(通用的)迭代器,算法可以“泛化”到不同类型的容器上
■ 如课程中的find函数,借助于迭代器,不用关心底层的容器
容器
● 课程介绍了vector,deque,list,主要是使用方面的细节和规则
● Vector:存放任意类别的动态数组
○ 使用时#include <vector>
○ 创建vector
○ 向vector添加元素:v.pushback(a)
○ 判断vector是否为空:v.empty()
○ 获得vector的大小:v.size()
○ 访问元素
■ v[8] 没有越界检查
■ v.at(8) 由越界检查,速度慢
○ 删除元素:
■ clear
■ pop_back
■ erase
● Deque:
○ push_front: 压入元素
○ pop_front: 弹出元素
● List:双向列表
○ 添加元素:push_back, push_front
○ 判断是否为空:l.empty(), I.size()
○ 删除元素
■ clear
■ pop_back
■ pop_front
■ remove
■ erase
○ 插入元素:
■ insert
○ 粘结
■ splice
网友评论