C++ 进阶 模板和STL
2021-01-02 07:31
标签:clip enc _each 实用 另一个 概念 不同 实际应用 结构 模板就是建立通用的模具,大大提高复用性 模板的特点: C++另一种编程思想称为 泛型编程 ,主要利用的技术就是模板 C++提供两种模板机制:函数模板和类模板 函数模板作用: 建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表。 语法: 解释: template --- 声明创建模板 typename --- 表面其后面的符号是一种数据类型,可以用class代替 T --- 通用的数据类型,名称可以替换,通常为大写字母 示例: 总结: 注意事项: 自动类型推导,必须推导出一致的数据类型T,才可以使用 模板必须要确定出T的数据类型,才可以使用 示例: 总结: 案例描述: 示例: 总结:模板可以提高代码复用,需要熟练掌握 普通函数与函数模板区别: 示例: 总结:建议使用显示指定类型的方式,调用函数模板,因为可以自己确定通用类型T 调用规则如下: 示例: 总结:既然提供了函数模板,最好就不要提供普通函数,否则容易出现二义性 局限性: 例如: 在上述代码中提供的赋值操作,如果传入的a和b是一个数组,就无法实现了 再例如: 在上述代码中,如果T的数据类型传入的是像Person这样的自定义数据类型,也无法正常运行 因此C++为了解决这种问题,提供模板的重载,可以为这些特定的类型提供具体化的模板 示例: 总结: 类模板作用: 语法: 解释: template --- 声明创建模板 typename --- 表面其后面的符号是一种数据类型,可以用class代替 T --- 通用的数据类型,名称可以替换,通常为大写字母 示例: 总结:类模板和函数模板语法相似,在声明模板template后面加类,此类称为类模板 类模板与函数模板区别主要有两点: 示例: 总结: 类模板中成员函数和普通类中成员函数创建时机是有区别的: 示例: 总结:类模板中的成员函数并不是一开始就创建的,在调用时才去创建 学习目标: 一共有三种传入方式: 示例: 总结: 当类模板碰到继承时,需要注意一下几点: 示例: 总结:如果父类是类模板,子类需要指定出父类中T的数据类型 学习目标:能够掌握类模板中的成员函数类外实现 示例: 总结:类模板中成员函数类外实现时,需要加上模板参数列表 学习目标: 问题: 解决: 示例: person.hpp中代码: 类模板分文件编写.cpp中代码 总结:主流的解决方式是第二种,将类模板成员函数写到一起,并将后缀名改为.hpp 学习目标: 全局函数类内实现 - 直接在类内声明友元即可 全局函数类外实现 - 需要提前让编译器知道全局函数的存在 示例: 总结:建议全局函数做类内实现,用法简单,而且编译器可以直接识别 案例描述: 实现一个通用的数组类,要求如下: 示例: myArray.hpp中代码 类模板案例—数组类封装.cpp中 总结: 能够利用所学知识点实现通用的数组 长久以来,软件界一直希望建立一种可重复利用的东西 C++的面向对象和泛型编程思想,目的就是复用性的提升 大多情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作 为了建立数据结构和算法的一套标准,诞生了STL STL大体分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器 容器:置物之所也 STL容器就是将运用最广泛的一些数据结构实现出来 常用的数据结构:数组, 链表,树, 栈, 队列, 集合, 映射表 等 这些容器分为序列式容器和关联式容器两种: ? 序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置。 算法:问题之解法也 有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms) 算法分为:质变算法和非质变算法。 质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等 非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等 迭代器:容器和算法之间粘合剂 提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。 每个容器都有自己专属的迭代器 迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针 迭代器种类: 常用的容器中迭代器种类为双向迭代器,和随机访问迭代器 了解STL中容器、算法、迭代器概念之后,我们利用代码感受STL的魅力 STL中最常用的容器为Vector,可以理解为数组,下面我们将学习如何向这个容器中插入数据、并遍历这个容器 容器: 算法: 迭代器: 示例: 学习目标:vector中存放自定义数据类型,并打印输出 示例: 学习目标:容器中嵌套容器,我们将所有数据进行遍历输出 示例: 本质: string和char * 区别: 特点: string 类内部封装了很多成员方法 例如:查找find,拷贝copy,删除delete 替换replace,插入insert string管理char*所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责 构造函数原型: 示例: 总结:string的多种构造方式没有可比性,灵活使用即可 功能描述: 赋值的函数原型: 示例: 总结: ? string的赋值方式很多, 功能描述: 函数原型: 示例: 总结:字符串拼接的重载版本很多,初学阶段记住几种即可 功能描述: 函数原型: 示例: 总结: 功能描述: 比较方式: = 返回 0 > 返回 1
函数原型: 示例: 总结:字符串对比主要是用于比较两个字符串是否相等,判断谁大谁小的意义并不是很大 string中单个字符存取方式有两种 示例: 总结:string字符串中单个字符存取有两种方式,利用 [ ] 或 at 功能描述: 函数原型: 示例: 总结:插入和删除的起始下标都是从0开始 功能描述: 函数原型: 示例: 总结:灵活的运用求子串功能,可以在实际开发中获取有效的信息 功能: vector与普通数组区别: 动态扩展: 功能描述: 函数原型: 示例: 总结:vector的多种构造方式没有可比性,灵活使用即可 功能描述: 函数原型: 示例: 总结: vector赋值方式比较简单,使用operator=,或者assign都可以 功能描述: 函数原型: ? //如果容器变短,则末尾超出容器长度的元素被删除。 ? //如果容器变短,则末尾超出容器长度的元素被删除 示例: 总结: 功能描述: 函数原型: 示例: 总结: 功能描述: 函数原型: 示例: 总结: 功能描述: 函数原型: 示例: 总结:swap可以使两个容器互换,可以达到实用的收缩内存效果 功能描述: 函数原型: 示例:C++提高编程
1 模板
1.1 模板的概念
1.2 函数模板
1.2.1 函数模板语法
template
//交换整型函数
void swapInt(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
//交换浮点型函数
void swapDouble(double& a, double& b) {
double temp = a;
a = b;
b = temp;
}
//利用模板提供通用的交换函数
template
1.2.2 函数模板注意事项
//利用模板提供通用的交换函数
template
1.2.3 函数模板案例
//交换的函数模板
template
1.2.4 普通函数与函数模板的区别
//普通函数
int myAdd01(int a, int b)
{
return a + b;
}
//函数模板
template
1.2.5 普通函数与函数模板的调用规则
//普通函数与函数模板调用规则
void myPrint(int a, int b)
{
cout
void myPrint(T a, T b)
{
cout
void myPrint(T a, T b, T c)
{
cout (a, b); //调用函数模板
//3、函数模板也可以发生重载
int c = 30;
myPrint(a, b, c); //调用重载的函数模板
//4、 如果函数模板可以产生更好的匹配,优先调用函数模板
char c1 = ‘a‘;
char c2 = ‘b‘;
myPrint(c1, c2); //调用函数模板
}
int main() {
test01();
system("pause");
return 0;
}
1.2.6 模板的局限性
template
template
#include
1.3 类模板
1.3.1 类模板语法
template
#include
1.3.2 类模板与函数模板区别
#include
1.3.3 类模板中成员函数创建时机
class Person1
{
public:
void showPerson1()
{
cout
class MyClass
{
public:
T obj;
//类模板中的成员函数,并不是一开始就创建的,而是在模板调用时再生成
void fun1() { obj.showPerson1(); }
void fun2() { obj.showPerson2(); }
};
void test01()
{
MyClass
1.3.4 类模板对象做函数参数
#include
1.3.5 类模板与继承
template
1.3.6 类模板成员函数类外实现
#include
1.3.7 类模板分文件编写
#pragma once
#include
#include
1.3.8 类模板与友元
#include
1.3.9 类模板案例
#pragma once
#include
#include "myArray.hpp"
#include
2 STL初识
2.1 STL的诞生
2.2 STL基本概念
2.3 STL六大组件
2.4 STL中容器、算法、迭代器
? 关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
种类
功能
支持运算
输入迭代器
对数据的只读访问
只读,支持++、==、!=
输出迭代器
对数据的只写访问
只写,支持++
前向迭代器
读写操作,并能向前推进迭代器
读写,支持++、==、!=
双向迭代器
读写操作,并能向前和向后操作
读写,支持++、--,
随机访问迭代器
读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器
读写,支持++、--、[n]、-n、、>=
2.5 容器算法迭代器初识
2.5.1 vector存放内置数据类型
vector
for_each
vector
#include
2.5.2 Vector存放自定义数据类型
#include
2.5.3 Vector容器嵌套容器
#include
3 STL- 常用容器
3.1 string容器
3.1.1 string基本概念
3.1.2 string构造函数
string();
//创建一个空的字符串 例如: string str;string(const char* s);
//使用字符串s初始化string(const string& str);
//使用一个string对象初始化另一个string对象string(int n, char c);
//使用n个字符c初始化#include
3.1.3 string赋值操作
string& operator=(const char* s);
//char*类型字符串 赋值给当前的字符串string& operator=(const string &s);
//把字符串s赋给当前的字符串string& operator=(char c);
//字符赋值给当前的字符串string& assign(const char *s);
//把字符串s赋给当前的字符串string& assign(const char *s, int n);
//把字符串s的前n个字符赋给当前的字符串string& assign(const string &s);
//把字符串s赋给当前字符串string& assign(int n, char c);
//用n个字符c赋给当前字符串//赋值
void test01()
{
string str1;
str1 = "hello world";
cout
operator=
这种方式是比较实用的3.1.4 string字符串拼接
string& operator+=(const char* str);
//重载+=操作符string& operator+=(const char c);
//重载+=操作符string& operator+=(const string& str);
//重载+=操作符string& append(const char *s);
//把字符串s连接到当前字符串结尾string& append(const char *s, int n);
//把字符串s的前n个字符连接到当前字符串结尾string& append(const string &s);
//同operator+=(const string& str)string& append(const string &s, int pos, int n);
//字符串s中从pos开始的n个字符连接到字符串结尾//字符串拼接
void test01()
{
string str1 = "我";
str1 += "爱玩游戏";
cout
3.1.5 string查找和替换
int find(const string& str, int pos = 0) const;
//查找str第一次出现位置,从pos开始查找int find(const char* s, int pos = 0) const;
//查找s第一次出现位置,从pos开始查找int find(const char* s, int pos, int n) const;
//从pos位置查找s的前n个字符第一次位置int find(const char c, int pos = 0) const;
//查找字符c第一次出现位置int rfind(const string& str, int pos = npos) const;
//查找str最后一次位置,从pos开始查找int rfind(const char* s, int pos = npos) const;
//查找s最后一次出现位置,从pos开始查找int rfind(const char* s, int pos, int n) const;
//从pos查找s的前n个字符最后一次位置int rfind(const char c, int pos = 0) const;
//查找字符c最后一次出现位置string& replace(int pos, int n, const string& str);
//替换从pos开始n个字符为字符串strstring& replace(int pos, int n,const char* s);
//替换从pos开始的n个字符为字符串s//查找和替换
void test01()
{
//查找
string str1 = "abcdefgde";
int pos = str1.find("de");
if (pos == -1)
{
cout
3.1.6 string字符串比较
int compare(const string &s) const;
//与字符串s比较int compare(const char *s) const;
//与字符串s比较//字符串比较
void test01()
{
string s1 = "hello";
string s2 = "aello";
int ret = s1.compare(s2);
if (ret == 0) {
cout 0)
{
cout
3.1.7 string字符存取
char& operator[](int n);
//通过[]方式取字符char& at(int n);
//通过at方法获取字符void test01()
{
string str = "hello world";
for (int i = 0; i
3.1.8 string插入和删除
string& insert(int pos, const char* s);
//插入字符串string& insert(int pos, const string& str);
//插入字符串string& insert(int pos, int n, char c);
//在指定位置插入n个字符cstring& erase(int pos, int n = npos);
//删除从Pos开始的n个字符//字符串插入和删除
void test01()
{
string str = "hello";
str.insert(1, "111");
cout
3.1.9 string子串
string substr(int pos = 0, int n = npos) const;
//返回由pos开始的n个字符组成的字符串//子串
void test01()
{
string str = "abcdefg";
string subStr = str.substr(1, 3);
cout
3.2 vector容器
3.2.1 vector基本概念
3.2.2 vector构造函数
vector
//采用模板实现类实现,默认构造函数vector(v.begin(), v.end());
//将v[begin(), end())区间中的元素拷贝给本身。vector(n, elem);
//构造函数将n个elem拷贝给本身。vector(const vector &vec);
//拷贝构造函数。#include
3.2.3 vector赋值操作
vector& operator=(const vector &vec);
//重载等号操作符assign(beg, end);
//将[beg, end)区间中的数据拷贝赋值给本身。assign(n, elem);
//将n个elem拷贝赋值给本身。#include
3.2.4 vector容量和大小
empty();
//判断容器是否为空capacity();
//容器的容量size();
//返回容器中元素的个数resize(int num);
//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。resize(int num, elem);
//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。#include
3.2.5 vector插入和删除
push_back(ele);
//尾部插入元素elepop_back();
//删除最后一个元素insert(const_iterator pos, ele);
//迭代器指向位置pos插入元素eleinsert(const_iterator pos, int count,ele);
//迭代器指向位置pos插入count个元素eleerase(const_iterator pos);
//删除迭代器指向的元素erase(const_iterator start, const_iterator end);
//删除迭代器从start到end之间的元素clear();
//删除容器中所有元素#include
3.2.6 vector数据存取
at(int idx);
//返回索引idx所指的数据operator[];
//返回索引idx所指的数据front();
//返回容器中第一个数据元素back();
//返回容器中最后一个数据元素#include
3.2.7 vector互换容器
swap(vec);
// 将vec与本身的元素互换#include
3.2.8 vector预留空间
reserve(int len);
//容器预留len个元素长度,预留位置不初始化,元素不可访问。#include
下一篇:五、Java - 集合