网站开发具体工作有那些,重庆招标投标公共资源交易中心,邢台今天的招工信息,成都私家花园设计公司哪家好C 提高编程 主要针对C泛型编程和STL技术
一、 模板 1、 概念 模板就是建立通用的模具#xff0c;大大提高代码的复用性
模板特点
模板不可以直接使用#xff0c;它只是一个框架 模板的通用并不是万能的 2、 函数模板 C 另一种编程思想为泛型编程#xff0c;主要利用的…C 提高编程 主要针对C泛型编程和STL技术
一、 模板 1、 概念 模板就是建立通用的模具大大提高代码的复用性
模板特点
模板不可以直接使用它只是一个框架 模板的通用并不是万能的 2、 函数模板 C 另一种编程思想为泛型编程主要利用的技术就是模板 C 提供两种模板机制函数模板 和 类模板 2.1 函数模板语法 函数模板的作用建立一个通用函数其函数返回值类型和形参类型可以不具体确定用一个虚拟的类型来代表
语法
templatetypename T
函数声明或定义参数
template声明创建模板 typename表明其后面的符号是一种数据类型可以用class来代替 T通用的数据类型名称可以替换通常为大写字母
// 两个整型交换函数
void swap(int a, int b)
{int temp a;a b; b temp;
}
// 交换浮点型的函数
void swap(double a, double b)
{double temp a;a b;b temp;
}
// 函数模板
template typename T // 声明模板告诉编译器后面代码紧跟着T不要报错T是一个通用的数据类型
void m_swap(T a, T b)
{T temp a;a b;b temp;
}
void test()
{int a 1;int b 3;double a1 4;double b1 5;/* swap(a, b);cout a b endl;swap(a1, b1);cout a1 b1 endl; */// 使用函数模板// 1、 自动推导m_swap(a, b);cout a b endl;// 2、 显示指定类型m_swapint(a, b);cout a b endl;
}模板可以将数据类型参数化
模板的使用方法
自动推导 显示指定类型 2.2 注意事项 注意事项
自动推导数据类型必须推导出一致的数据类型 T才可以使用 模板必须要确定出 T 的数据类型才可以使用 2.3 普通函数和函数模板的区别 普通函数调用时可以发生自动类型转换隐式类型装换 函数模板调用时如果利用自动类型推导不会发生隐式类型装换 如果利用显示指定类型的方法可以发生隐式类型转换 2.4 普通函数和函数模板的调用规则 调用规则如下
如果函数模板和普通函数都可以实现优先调用普通函数
可以通过空模板参数列表强制调用函数模板
void myPrint(int a, int b)
{cout a b endl;cout 普通函数 endl;
}
templatetypename T
void myPrint(T a, T b)
{cout a b endl;cout 模板函数 endl;
}void test()
{int a 10;int b 20;myPrint(a, b); // 空模板参数列表调用模板函数
}函数模板也可以发生重载
如果函数模板可以产生更好的匹配模式优先调用函数模板
void myPrint(int a, int b)
{cout a b endl;cout 普通函数 endl;
}
templatetypename T
void myPrint(T a, T b)
{cout a b endl;cout 模板函数 endl;
}void test()
{char a a;char b b;myPrint(a, b); // 函数模板可以产生更好的匹配
}既然提供了函数模板最好不要提供普通函数否则容易出现二义性
2.5 模板的局限性 模板的通用性并不是万能的 如果传入的是一个元组以及自定义数据类型就无法实现了
因此C为了解决这种问题提供模板的重载可以为这些特定的类型提供具体化模板
// 模板重载
// 对比两个数据是否相等
class Person
{
public:Person(string name, int age){m_Age age;m_Name name;}string m_Name;int m_Age;
};
templateclass T
bool myCompare(T a, T b) // 如果传入的是一个自定义数据类型呢
{if (a b){return true;}else{return false;}
}
// 利用具体化Person的版本实现代码具体化优先调用
// 也可以使用运算符重载
templatebool myCompare(Person p1, Person p2)
{if (p1.m_Name p2.m_Name p1.m_Age p2.m_Age){return true;}else{return false;}
}
void test()
{Person p1(Tom, 10);Person p2(Tom, 10);cout myCompare(p1, p2) endl;
}学习模板并不是为了写模板而是在STL中能够运用系统提供的模板
3、 类模板 3.1 类模板语法 类模板作用
建立一个通用类类中成员数据类型可以不具体制定用一个虚拟的类型代表 语法
templatetypename T
参数template声明创建模板
typename表明其后面的符号是一种数据类型可以用class来代替
T通用的数据类型名称可以替换通常为大写字母
templatetypename NameT, typename AgeT
class Person
{
public:Person(NameT name, AgeT age){m_Age age;m_Name name;}NameT m_Name;AgeT m_Age;
};
void test()
{Personstring, int(Tom, 30); // 调用-只有一种调用方式
}3.2 类模板和函数模板的区别 类模板与函数模板区别主要有两点
类模板没有自动类型推导的使用方式
类模板在模板参数列表中可以有默认参数
templatetypename NameT, typename AgeT int // 默认参数
class Person
{
public:Person(NameT name, AgeT age){m_Age age;m_Name name;}NameT m_Name;AgeT m_Age;
};
void test()
{Personstring(Tom, 30);
}3.3 使用时机 类模板中成员函数和普通类中成员函数创建时机是有区别的
普通类中的成员函数一开始就可以创建 类模板中的成员函数在调用时才创建
class Person1
{
public:void show(){cout Person1 endl;}};templatetypename T
class Person
{
public:// 没调用其不会编译因为无法确定T的数据类型T p1;void func1(){p1.show();}};
void test()
{PersonPerson1 p;p.func1();
}3.4 类模板对象函数做参数 类模板实例出的对象向函数传参
一共有三种传入方式
指定传入的数据类型直接显示对象的数据类型
// 类模板做函数的参数
templateclass T1, class T2
class Person
{
public:Person(T1 name, T2 age){m_Name name;m_Age age;}T1 m_Name;T2 m_Age;void showPerson(){cout name: m_Name age: m_Age endl;}
};
// 指定传入类型
void printPerson1(Personstring, int p)
{p.showPerson();
}
// 参数模板化
templateclass T1, class T2
void printPerson2(PersonT1, T2 p)
{p.showPerson();cout T1的类型为 typeid(T1).name() endl;cout T2的类型为 typeid(T2).name() endl;
}
// 整个类模板化
templateclass T
void printPerson3(T p)
{p.showPerson();
}
void test()
{Personstring, int p(Tom, 12);printPerson1(p);printPerson2(p);printPerson3(p);
}二、 STL 初识 1、 基本概念 STL 基本模板库 STL 从广义上分为容器、算法和迭代器 容器和算法事件通过迭代器无缝连接 STL 几乎所有的代码都采用了模板类或模板函数 2、 STL 六大组件 STL 大体分为六大组件容器、算法、迭代器、仿函数、适配器配接器、空间配置器
容器各种数据结构vector、list、deque、set、map等用来存放数据 算法各种常用的算法如sort、find、copy、for_each等 迭代器扮演了容器和算法之间的胶合剂 仿函数行为类似的函数可作为算法的某种策略 适配器一种用来修饰容器或者仿函数或迭代器接口的东西 空间配置器负责空间的配置和管理 2.1 容器、算法、迭代器 容器置物之所也
STL 容器就是将运用最广泛的一些数据结构实现出来
常用的数据结构数组、列表、树、栈、队列、集合、映射表等
这些容器分为序列式容器和关联式容器两种
序列式容器强调值的排序序列式容器中的每个元素均有固定的位置 关联式容器二叉树结构各元素之间没有严格的物理上的顺序关系 算法问题之解也
有限的步骤解决逻辑或数学上的问题这叫做算法
算法分为质变算法和非质变算法
质变算法是指运算过程中会更改区间内的元素的内容例如拷贝、替换、删除等等 非质变算法是指运算过程中不会更改区间内的元素内容例如查找、计数、遍历、寻找极值等等 迭代器容器和算法之间粘合剂
提供一种方法使之能够依序寻访某个容器所含有的各个元素而又无需暴露该容器的内部表示方式
每个容器都有自己专属的迭代器
迭代器使用非常类似于指针
迭代器种类 常用的容器中迭代器种类为双向迭代器和随机访问迭代器
3、 迭代器初始 3.1 vector 存放内置数据类型 容器vector
算法for_each
迭代器vector::iterator
#include vector // vector 头文件
#include algorithm // 标准算法头文件void printVector(int value)
{cout value endl;
}
// vector 存放内置数据类型
void test()
{// 创建一个 vector 容器——数组vectorint v;// 向容器中插入数据v.push_back(10); // 尾插数据v.push_back(11);v.push_back(12);// 通过迭代器访问容器中的数据vectorint::iterator itBegin v.begin(); // 起始迭代器指向容器中第一个元素当做指针使用vectorint::iterator itEnd v.end(); // 结束迭代器指向容器最后一个元素的下一个位置// 第一种遍历方式while (itBegin ! itEnd){cout *itBegin endl;itBegin;}// 第二种遍历方式for (vectorint::iterator it v.begin(); it ! v.end(); it){cout *it endl;}// 第三种遍历方式for_each(v.begin(), v.end(), printVector); // 回调函数
}