asp图片源码网站,自建网站餐饮服务提供者应当在通信主管部门备案后,o2o网站建设怎么样,南宁seo公司文章目录前言一、模板1.1 模板的概念1.2 函数模板1.2.1 函数模板语法1.2.2 函数模板注意事项1.2.3 函数模板案例复习#xff1a;计算数组长度1.2.4 普通函数与函数模板的区别1.2.5 普通函数与函数模板的调用规则1.2.6 模板的局限性1.3 类模板1.3.1 类模板语法1.3.2 类模板与函…
文章目录前言一、模板1.1 模板的概念1.2 函数模板1.2.1 函数模板语法1.2.2 函数模板注意事项1.2.3 函数模板案例复习计算数组长度1.2.4 普通函数与函数模板的区别1.2.5 普通函数与函数模板的调用规则1.2.6 模板的局限性1.3 类模板1.3.1 类模板语法1.3.2 类模板与函数模板区别1.3.3 类模板中成员函数创建时机1.3.4 类模板对象做函数参数查看模板参数类型的方法1.3 后续部分待学应该暂时用不到还有需要复习一下类和对象的知识1.3.5 类模板与继承1.3.6 类模板成员函数类外实现1.3.7 类模板分文件编写1.3.8 类模板与友元1.3.9 类模板案例二、STL初识2.1 STL的诞生2.2 STL基本概念2.3 STL六大组件2.4 STL中容器、算法、迭代器总结 #pic_center前言 只是为方便学习不做其他用途原作者为黑马程序员 B站配套视频 https://www.bilibili.com/video/BV1et411b73Z 本阶段主要针对C泛型编程和STL技术做详细讲解探讨C更深层次的使用 一、模板
1.1 模板的概念 模板就会通用的模具大大提高复用性。
例如生活中的一寸照片、PPT模板。 模板特点 模板不可以直接使用它只是一个框架模板的通用并不是万能的
1.2 函数模板
C另一种编程思想称为泛型编程主要利用的技术就是模板C提供两种模板机制函数模板和类模板。
1.2.1 函数模板语法
函数模板作用 建立一个通用的函数其函数返回值类型和形参类型可以不具体制定用一个虚拟的类型来代表。 语法 templatetypename T
函数声明或定义解释: template——声明创建模板 typena me——表明其后面的 符号为一种数据类型可以用class代替。 T——通用的数据类型名称可以替换通常为大写字母。 #includeiostream
using namespace std;//函数模板
//两个整型交换
void SwapInt(int a, int b)
{int temp b;b a;a temp;
}
//两个浮点型交换
void SwapDouble(double a, double b)
{double temp a;a b;b temp;
}//函数模板
//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错T是一个通用数据类型
templatetypename T
void MySwap(T a, T b)
{T Temp a;a b;b Temp;
}void test01()
{int a 10;int b 20;//利用函数模板进行交换//1.自动类型推导MySwap(a, b);cout a endl;cout b endl;double c 11.1;double d 12.2;//2.显示指定类型MySwapdouble(c, d);cout c endl;cout d endl;
}
int main(void)
{test01();system(pause);return 0;
}
1.2.2 函数模板注意事项 注意事项: 自动类型推导必须推导出一致的数据类型T,才可以使用模板必须要确定出T的数据类型才可以使用 示例: #includeiostream
using namespace std;//利用模板提供通用的交换函数
templateclass T
void mySwap(T a, T b)
{T temp a;a b;b temp;
}// 1、自动类型推导必须推导出一致的数据类型T,才可以使用
void test01()
{int a 10;int b 20;char c c;mySwap(a, b); // 正确可以推导出一致的T//mySwap(a, c); // 错误推导不出一致的T类型
}// 2、模板必须要确定出T的数据类型才可以使用
templateclass T
void func()
{cout func 调用 endl;
}void test02()
{//func(); //错误模板不能独立使用必须确定出T的类型funcint(); //利用显示指定类型的方式给T一个类型才可以使用该模板
}int main() {test01();test02();system(pause);return 0;
}
总结使用模板时必须确定出通用数据类型T并且能够推导出一致的类型
1.2.3 函数模板案例
案例描述
利用函数模板封装一个排序的函数可以对不同数据类型数组进行排序排序规则从大到小排序算法为选择排序分别利用char数组和int数组进行测试 示例
#includeiostream
using namespace std;
//实现通用 对数组进行排序的函数
//规则 从大到小
//算法 选择
//测试 char 数组 int 数组
//交换的函数模板
templateclass T
void mySwap(T a, T b)
{T temp a;a b;b temp;
}templateclass T
void mySort(T arr[], int len)
{for (int i 0; i len; i){int max i;//认定最大值的下标for (int j i 1; j len; j){//认定的最大值比遍历出的数值要小说明j下标的元素才是真正的最大值if (arr[max] arr[j]){max j;}}if (max ! i){//交换max和i元素mySwap(arr[max], arr[i]);}}
}//打印数组模板
templateclass T
void myPrint(T arr[], int len)
{for (int i 0; i len; i){cout arr[i] ;}cout endl;
}void test01()
{char charArr[] badcfe;int num sizeof(charArr) / sizeof(char);mySort(charArr, num);myPrint(charArr, num);
}
void test02()
{int intArr[] { 2,3,5,9,7,1,4,8,6 };int num sizeof(intArr) / sizeof(int);mySort(intArr, num);myPrint(intArr, num);
}
int main(void)
{test01();test02();return 0;
}复习计算数组长度 1.2.4 普通函数与函数模板的区别 普通函数与函数模板区别
普通函数调用时可以发生自动类型转换隐式类型转换函数模板调用时如果利用自动类型推导不会发生隐式类型转换如果利用显示指定类型的方式可以发生隐式类型转换 隐式类型转换的理解 #includeiostream
using namespace std;
//普通函数与函数模板的区别
//普通函数调用可以发生隐式类型转换
//函数模板用自动类型推导不可以发生隐式类型转换
// 函数模板用显式指定类型 可以发生隐式类型转换//普通函数隐式类型转换
int myAdd01(int a, int b)
{return a b;
}//函数模板
templateclass T
T myAdd02(T a, T b)
{return a b;
}void test01()
{int a 10;int b 20;char c c; //正确将char类型的c隐式转换为int类型 c 对应 ASCII码 99cout myAdd01(a, c) endl;//自动类型推导不行//cout myAdd02(a, c) endl;//显式指定类型行cout myAdd02int(a, c) endl;
}int main(void)
{test01();system(pause);return 0;
}总结:建议使用显式指定类型的方式调用函数模板因为可以自己确定通用类型T 1.2.5 普通函数与函数模板的调用规则 调用规则如下
如果函数模板和普通函数都可以实现优先调用普通函数可以通过空模板参数列表来强制调用函数模板函数模板也可以发生重载如果函数模板可以产生更好的匹配,优先调用函数模板 #includeiostream
using namespace std;//普通函数与函数模板调用规则
void myPrint(int a, int b)
{cout 调用的普通函数 endl;
}templatetypename T
void myPrint(T a, T b)
{cout 调用的模板 endl;
}templatetypename T
void myPrint(T a, T b, T c)
{cout 调用重载的模板 endl;
}void test01()
{//1、如果函数模板和普通函数都可以实现优先调用普通函数// 注意 如果告诉编译器 普通函数是有的但只是声明没有实现或者不在当前文件内实现就会报错找不到int a 10;int b 20;myPrint(a, b); //调用普通函数//2、可以通过空模板参数列表来强制调用函数模板myPrint(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 模板的局限性 局限性
模板的通用性并不是万能的
例如 templateclass Tvoid f(T a, T b){ a b;}在上述代码中提供的赋值操作如果传入的a和b是一个数组就无法实现了 再例如 templateclass Tvoid f(T a, T b){ if(a b) { ... }}在上述代码中如果T的数据类型传入的是像Person这样的自定义数据类型也无法正常运行 因此C为了解决这种问题提供模板的重载可以为这些特定的类型提供具体化的模板 #includeiostream
using namespace std;#include stringclass Person
{
public:Person(string name, int age){this-m_Name name;this-m_Age age;}string m_Name;int m_Age;
};//普通函数模板
templateclass T
bool myCompare(T a, T b)
{if (a b){return true;}else{return false;}
}//具体化显示具体化的原型和定意思以template开头并通过名称来指出类型
//具体化优先于常规模板
template bool myCompare(Person p1, Person p2)
{if (p1.m_Name p2.m_Name p1.m_Age p2.m_Age){return true;}else{return false;}
}void test01()
{int a 10;int b 20;//内置数据类型可以直接使用通用的函数模板bool ret myCompare(a, b);if (ret){cout a b endl;}else{cout a ! b endl;}
}void test02()
{Person p1(Tom, 10);Person p2(Tom, 10);//自定义数据类型不会调用普通的函数模板//可以创建具体化的Person数据类型的模板用于特殊处理这个类型bool ret myCompare(p1, p2);if (ret){cout p1 p2 endl;}else{cout p1 ! p2 endl;}
}int main() {test01();test02();system(pause);return 0;
}总结
利用具体化的模板可以解决自定义类型的通用化学习模板并不是为了写模板而是在STL能够运用系统提供的模板
1.3 类模板
1.3.1 类模板语法 类模板作用 建立一个通用类类中的成员 数据类型可以不具体制定用一个虚拟的类型来代表。 类模板语法 templatetypename T
类示例 #includeiostream
using namespace std;#include string
//类模板
templateclass NameType, class AgeType
class Person
{
public:Person(NameType name, AgeType age){this-mName name;this-mAge age;}void showPerson(){cout name: this-mName age: this-mAge endl;}
public:NameType mName;AgeType mAge;
};void test01()
{// 指定NameType 为string类型AgeType 为 int类型Personstring, intP1(孙悟空, 999);P1.showPerson();
}int main() {test01();system(pause);return 0;
}总结类模板和函数模板语法相似在声明模板template后面加类此类称为类模板 1.3.2 类模板与函数模板区别 类模板与函数模板区别主要有两点 类模板没有自动类型推导的使用方式类模板在模板参数列表中可以有默认参数 #includeiostream
using namespace std;#include string
//类模板
templateclass NameType, class AgeType int
class Person
{
public:Person(NameType name, AgeType age){this-mName name;this-mAge age;}void showPerson(){cout name: this-mName age: this-mAge endl;}
public:NameType mName;AgeType mAge;
};//1、类模板没有自动类型推导的使用方式
void test01()
{// Person p(孙悟空, 1000); // 错误 类模板使用时候不可以用自动类型推导Person string, intp(孙悟空, 1000); //必须使用显示指定类型的方式使用类模板p.showPerson();
}//2、类模板在模板参数列表中可以有默认参数
void test02()
{Person string p(猪八戒, 999); //类模板中的模板参数列表 可以指定默认参数p.showPerson();
}int main() {test01();test02();system(pause);return 0;
}总结
类模板使用只能用显示指定类型方式类模板中的模板参数列表可以有默认参数
1.3.3 类模板中成员函数创建时机 类模板中成员函数和普通类中成员函数创建时机是有区别的 普通类中的成员函数一开始就可以创建类模板中的成员函数在调用时才创建
#includeiostream
using namespace std;class Person1
{
public:void showPerson1(){cout Person1 show endl;}
};class Person2
{
public:void showPerson2(){cout Person2 show endl;}
};templateclass T
class MyClass
{
public:T obj;//类模板中的成员函数并不是一开始就创建的而是在模板调用时再生成void fun1() { obj.showPerson1(); }void fun2() { obj.showPerson2(); }};void test01()
{MyClassPerson1 m;m.fun1();//m.fun2();//编译会出错说明函数调用才会去创建成员函数
}int main() {test01();system(pause);return 0;
}总结类模板中的成员函数并不是一开始就创建的在调用时才去创建
1.3.4 类模板对象做函数参数 学习目标 类模板实例化出的对象向函数传参的方式 一共有三种传入方式 指定传入的类型 — 直接显示对象的数据类型参数模板化 — 将对象中的参数变为模板进行传递整个类模板化 — 将这个对象类型 模板化进行传递
查看模板参数类型的方法 #includeiostream
using namespace std;#include string
//类模板
templateclass NameType, class AgeType int
class Person
{
public:Person(NameType name, AgeType age){this-mName name;this-mAge age;}void showPerson(){cout name: this-mName age: this-mAge endl;}
public:NameType mName;AgeType mAge;
};//1、指定传入的类型
void printPerson1(Personstring, int p)
{p.showPerson();
}
void test01()
{Person string, int p(孙悟空, 100);printPerson1(p);
}//2、参数模板化
template class T1, class T2
void printPerson2(PersonT1, T2 p)
{p.showPerson();cout T1的类型为 typeid(T1).name() endl;cout T2的类型为 typeid(T2).name() endl;
}
void test02()
{Person string, int p(猪八戒, 90);printPerson2(p);
}//3、整个类模板化
templateclass T
void printPerson3(T p)
{cout T的类型为 typeid(T).name() endl;p.showPerson();}
void test03()
{Person string, int p(唐僧, 30);printPerson3(p);
}int main() {test01();test02();test03();system(pause);return 0;
}总结
通过类模板创建的对象可以有三种方式向函数中进行传参使用比较广泛是第一种指定传入的类型
1.3 后续部分待学应该暂时用不到还有需要复习一下类和对象的知识
1.3.5 类模板与继承 当类模板碰到继承时需要注意一下几点 当子类继承的父类是一个类模板时子类在声明的时候要指定出父类中T的类型如果不指定编译器无法给子类分配内存如果想灵活指定出父类中T的类型子类也需变为类模板
总结如果父类是类模板子类需要指定出父类中T的数据类型
1.3.6 类模板成员函数类外实现 学习目标能够掌握类模板中的成员函数类外实现 总结类模板中成员函数类外实现时需要加上模板参数列表
1.3.7 类模板分文件编写 学习目标 掌握类模板成员函数分文件编写产生的问题以及解决方式 问题 类模板中成员函数创建时机是在调用阶段导致分文件编写时链接不到 解决 解决方式1直接包含.cpp源文件解决方式2将声明和实现写到同一个文件中并更改后缀名为.hpphpp是约定的名称并不是强制
总结
1.3.8 类模板与友元 学习目标 掌握类模板配合友元函数的类内和类外实现
全局函数类内实现 - 直接在类内声明友元即可
全局函数类外实现 - 需要提前让编译器知道全局函数的存在
总结建议全局函数做类内实现用法简单而且编译器可以直接识别
1.3.9 类模板案例 二、STL初识
2.1 STL的诞生
长久以来软件界一直希望建立一种可重复利用的东西C的面向对象和泛型编程思想目的就是复用性的提升大多情况下数据结构和算法都未能有一套标准,导致被迫从事大量重复工作为了建立数据结构和算法的一套标准,诞生了STL
2.2 STL基本概念
STL(Standard Template Library, 标准模板库)STL 从广义上分为: 容器(container) 算法(algorithm) 迭代器(iterator) 容器和算法之间通过迭代器进行无缝连接。STL 几乎所有的代码都采用了模板类或者模板函数
2.3 STL六大组件 STL大体分为六大组件分别是: 容器、算法、迭代器、仿函数、适配器配接器、空间配置器 容器各种数据结构如vector、list、deque、set、map等,用来存放数据。算法各种常用的算法如sort、find、copy、for_each等迭代器扮演了容器与算法之间的胶合剂。仿函数行为类似函数可作为算法的某种策略。适配器一种用来修饰容器或者仿函数或迭代器接口的东西。空间配置器负责空间的配置与管理。
2.4 STL中容器、算法、迭代器 容器置物之所也
STL容器就是将运用最广泛的一些数据结构实现出来
常用的数据结构数组, 链表,树, 栈, 队列, 集合, 映射表 等
这些容器分为序列式容器和关联式容器两种:
序列式容器:强调值的排序序列式容器中的每个元素均有固定的位置。关联式容器:二叉树结构各元素之间没有严格的物理上的顺序关系
总结 #pic_center
空格 空格 二维数
1
1
1