cpp学习笔记:模板
一、模板的作用
建立一个通用函数,其函数返回值类型和形参类型可以不具体确定,用一个虚拟的类型来代表。
template<typename T>
二、示例
1、不使用模板写两个交换变量数值
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;
}int main()
{int a = 10;int b = 20;SwapInt(a, b);cout << a << endl;cout << b << endl;system("pause");return 0;
}
2、使用模板交换两个变量数值
template<typename T>
void Swap(T& a,T&b)
{T temp = a;a = b;b = temp;
}int main()
{int a = 10;int b = 20;Swap(a, b); //自动推导类型Swap<int>(a, b); //显示指定类型cout << a << endl;cout << b << endl;system("pause");return 0;
}
三、使用模板时的注意事项
1、自动类型推导,必须推导出一致的数据类型T,才能使用
int a = 10;int b = 20;char c = 'c';Swap(a, b); //自动推导类型//Swap(a, c); //报错,自动推导时类型必须相同
2、模板必须要确定出T的数据类型,才可以使用
template<typename T>
void func()
{cout << "111" << endl;
}int main()
{//func(); //错误,模板不能独立使用,必须确定出T的类型func<int>(); //利用显示置定类型的方法,给T一个类型,才可以使用模板system("pause");return 0;
}
四、函数模板案例
案例描述:
①利用函数模板封装一个排序函数,可以对不同数据类型数组进行排序
②排序规则从大到小,排序算法为冒泡排序
③分别利用char数组和int数组进行测试
template<typename T>
void Swap(T &a,T &b)
{T temp = a;a = b;b = temp;
}template<class T>
void Sort(T arr[],int len)
{for (int i = 0; i < len - 1;i++){for (int j = 0; j < len - 1 - i;j++){if(arr[j]>arr[j+1]){Swap(arr[j], arr[j + 1]);}}}
}template<typename T>
void printArray(T arr[],int len)
{for (int i = 0; i < len;i++){cout << arr[i] << endl;}cout << endl;
}void text_char()
{char charArr[] = "qwerasd";int num = sizeof(charArr) / sizeof(char);Sort(charArr, num);printArray(charArr, num);
}void text_int()
{int intArr[] = {7, 4, 1, 8, 5, 0, 2, 9, 6, 3};int num = sizeof(intArr) / sizeof(intArr[0]);Sort(intArr, num);printArray(intArr, num);
}int main()
{//text_char();text_int();system("pause");return 0;
}
五、普通函数与函数模板调用规则
1、如果函数模板和普通模板都可以实现,优先调用普通函数
2、可以通过空模版参数列表来强制调用函数模板
3、函数模板也可以发生重载,此时调用函数模板
4、如果函数模板可以产生更好的匹配,优先调用函数模板
void myPrint(int a,int b)
{cout << "调用普通函数" << endl;
}template<typename T>
void myPrint(T a,T b)
{cout << "调用模板" << endl;
}template<typename T>
void myPrint(T a,T b,T c)
{cout << "调用重载模板" << endl;
}int main()
{int a = 10;int b = 20;//如果函数模板和普通模板都可以实现,优先调用普通函数myPrint(a, b);//可以通过空模版参数列表来强制调用函数模板myPrint<>(a, b);//函数模板也可以发生重载,此时调用函数模板int c = 30;myPrint(a, b, c);//如果函数模板可以产生更好的匹配,优先调用函数模板char c1 = 'a';char c2 = 'b';myPrint(c1, c2);system("pause");return 0;
}
六、模板的局限性
模板的通用性并不是万能的
例如:
template<typename T>
void f(T a,T b)
{a = b;
}
在上述代码中提供的幅值操作,如果传入的a和b是一个数组,就无法实现了。
template<class T>
void f(T a,T b)
{if(a>b){}
}
在上述代码中,如果T的数据类型传入的是Person这样的自定义数据类型,也无法正常运行。
因此,c++提供了模板的重载,可以为这些特定类型提供具体化的模板
示例:
class Person
{
public:Person(string name,int age){this->m_Name = name;this->m_Age = age;}public:string m_Name;int m_Age;
};//普通函数模板
template<class 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 text01()
{int a = 10;int b = 20;bool ret = myCompare(a, b);if(ret){cout << "a=b" << endl;}else{cout << "a!=b"<<endl;}
}void text02()
{Person p1("Tom", 10);Person p2("Tom", 10);bool ret = myCompare(p1, p2);if(ret){cout << "p1==p2" << endl;}else{cout << "p1!=p2" << endl;}
}int main()
{//text01();text02();system("pause");return 0;
}
七、类模板
作用:建立一个通用的类,类中成员的数据类型可以不具体制定,用一个虚拟的类型来代表。
template <class NameType,class AgeType>
class Person
{
public:Person(NameType name,AgeType age){this->name = name;this->age = age;}void showPerson(){cout << "name:" << this->name << " age:" << this->age << endl;}public:NameType name;AgeType age;
};void text01()
{Person<string, int> P1("猴子", 99);Person<int, float> P2(12, 1.11);P1.showPerson();P2.showPerson();
}
八、类模板与函数模板的区别
类模板没有自动类型推导的使用方式,且类模板在模板参数列表中可以用默认参数
void text01()
{//Person p("猴子", 1000); //类模板使用的时候,不可以用自动类型推导Person<string, int> p("孙悟空", 1000); //必须使用指定的类型方式p.showPerson();
}void text02()
{Person<string> p("猪八戒", 99); //类模板中的模板参数列表,可以指定默认参数p.showPerson();
}
九、类模板中成员函数创建时机
普通类中的成员函数一开始就可以创建
类模板中的成员函数在调用时才创建
十、类模板对象做函数参数
1、指定传入的类型:直接显示对象的数据类型
void printPerson1(Person<string,int> &p)
{p.showPerson();
}void text01()
{Person<string, int> p("孙悟空", 100);printPerson1(p);
}
2、参数模板化:将对象中的参数变为模板进行传递
template <class T1,class T2>
void printPerson2(Person<T1, T2>&p)
{p.showPerson();
}void text02()
{Person <string, int> p("猪八戒", 200);printPerson2(p);
}
3、整个类模板化:将这个对象类型模板化进行传递
template<class T>
void printPerson3(T &p)
{p.showPerson();
}void text03()
{Person<string, int> p("唐僧", 300);printPerson3(p);
}
十一、类模板与继承
1、当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
template<class T>
class Base
{T m;
};//class Son:public Base //错误,没有指出父类中T的类型
class Son:public Base<int> //必须指定一个类型
{
};void text01()
{Son s;
}
2、如果不指定,编译器无法给子类分配内存
3、如果想灵活指定出父类中T的内存,子类也需变为类模板
template<class T1,class T2>
class Son2:public Base<T2>
{
public:Son2(){cout << typeid(T1).name() << endl;cout << typeid(T2).name() << endl;}
};void text02()
{Son2<int, char> child;
}
十二、类模板成员函数类外实现
//类模板中成员函数类外实现
template<class T1,class T2>
class Person
{
public://成员函数类内声明Person(T1 name, T2 age);void showPerson();public:T1 m_name;T2 m_age;
};//构造函数类外实现
template <class T1,class T2>
Person<T1,T2>::Person(T1 name,T2 age)
{this->m_name = name;this->m_age = age;
}//成员函数类外实现
template<class T1,class T2>
void Person<T1,T2>::showPerson()
{cout << "姓名:" << this->m_name << " 年龄:" << this->m_age << endl;
}void text01()
{Person<string, int> p("abs", 10);p.showPerson();
}
十三、类模板与友元
全局函数类内实现:直接在类内声明友元即可
全局函数类外实现:需要提前让编译器知道全局函数的存在
//2、全局函数配合友元 类外实现 先做函数模板声明,下方在做函数模板定义,在做友元
template <class T1, class T2>class Person;template<class T1,class T2>
void printPerson2(Person<T1,T2> &p)
{cout << "类外实现 姓名:" << p.m_name << " 年龄:" << p.m_age<<endl;
}template<class T1,class T2>
class Person
{friend void printPerson(Person <T1,T2> &p){cout << "类内实现 姓名:" << p.m_name << " 年龄:" << p.m_age<<endl;}friend void printPerson2<>(Person<T1, T2> &p);public:Person(T1 name,T2 age){this->m_name=name;this->m_age = age;}private:T1 m_name;T2 m_age;
};//1、全局函数在类内实现
void text01()
{Person <string,int>p("Tom",20);printPerson(p);
}//2、全局函数在类外实现
void text02()
{Person <string,int>p("Jerry",20);printPerson2(p);
}
cpp学习笔记:模板相关推荐
- C++学习笔记:模板
C++学习笔记:模板 1.函数模板 2.类模板 2.1类模板注意事项 2.2类模板中函数的创建时机 2.3类模板对象作函数参数时 2.4类模板与继承 2.5类模板分文件编写 2.6类模板友元 2.6. ...
- 设计模式学习笔记——模板(Template)模式
设计模式学习笔记--模板(Template)模式 @(设计模式)[设计模式, 模板模式, template, 模板方法] 设计模式学习笔记模板Template模式 基本介绍 模板案例 类图 实现代码 ...
- 图论01.最短路专题_学习笔记+模板
图论01.最短路专题_学习笔记+模板 一.定义与性质 ● 需要的前导知识点 路径 最短路 有向图中的最短路.无向图中的最短路 单源最短路.每对结点之间的最短路 ● 最短路的性质 对于边权为正的图,任意 ...
- image是否有disabled属性_Vue学习笔记 模板语法、计算属性
点击上方"蓝字"关注我们吧! vue学习笔记 官网:https://cn.vuejs.org/v2/guide/ 1.vue体验 demo示例: image.png 示例代码: & ...
- C++模板学习笔记——模板实参
对于函数模板,编译器通过隐式推断模板实参.其中,从函数实参来确定模板实参的过程被称为模板实参推断.在模板实参推断过程中,编译器使用函数调用中的实参类型来寻找模板实参,用这些模板实参生成的函数版本与给定 ...
- C++学习笔记—模板与STL
C++提高编程 本阶段主要针对C++泛型编程和STL技术做详细讲解,探讨C++更深层的使用 1 模板 1.1 模板的概念 模板就是建立通用的模具,大大提高复用性 例如生活中的模板 一寸照片模板 PPT ...
- [C++]学习笔记——模板
针对C++泛型编程和STL技术做详细讲解,探讨C++更深层的使用. 1.模板 1.1模板的概念 模板就是建立通用的模具,大大提高复用性 日常生活例子帮助理解:一寸照片模板.PPT模板 1.2函数模板语 ...
- 菜鸟教程Cpp学习笔记
一.面向对象开发的特征 面向对象开发的四大特性: 封装 抽象 继承 多态 二.C++ 中的类型限定符 限定符 含义 const const 类型的对象在程序执行期间不能被修改改变. volatile ...
- C++学习笔记-------模板(template)
文章目录 1.函数模板 2.类模板 2.1类模板的基本使用 2.2类模板中的友元 3.模板默认参数 3.1模板函数的默认参数 3.2类模板默认参数 4.成员模板 4.1普通类的成员模板 4.2模板类的 ...
最新文章
- C语言----项目构建Make,Automake,CMake
- python运行速度和电脑配置有关系吗-学python最电脑配置有要求么
- linux创建更改目录,如何使用Linux中的单个命令创建新目录并更改它 | MOS86
- DataSource--DBCP--C3P0--DBUtils
- 用十条命令在一分钟内检查Linux服务器性能
- controller如何保证当前只有一个线程执行_聊聊Spring线程安全,读完之后,大部分程序员收藏了......
- 最实用的APP界面设计知识,有温度的APP设计(转)
- 传递json_开发技巧分享—JSON 数据格式及函数讲解
- 2018年7月第一周网站建站笔记
- Improving Opencv 4: The Core Functionality :Operations with images
- PAIP.提升安全性---更好的签名HASH算法
- 文本密度 php,基于最大文本密度的网页正文抽取方法
- Android App 启动时显示正在加载图片(源码)
- gms认证流程_Android P(9.0)GMS认证新要求
- 基于国密算法SM2非证书标识公钥密码技术(IPK)
- 新版个人所得税计算python_最新个税计算 / 个税计算器 小程序 wepy 开发
- 跟着团子学SAP PS:项目计划成本与项目预算设计思路
- Pyhon中利用GM(1,1)和ARIMA模型对卫星DCB值进行预测
- 节假日配置、工作日配置
- 骑士周游 探索访问