一文带你掌握C++模版

news/2024/9/23 6:32:09/

12. C++模板

什么是模板

模板编程也可以叫做泛型编程,忽略数据类型的一种编程方式

//求最值问题
int  Max(int a,int b)
{return a>b?a:b;    
}
double Max(int a,int b)
{return a>b?a:b;        
}
string Max(string a,string b)
{return a>b?a:b;        
}
//引入模板编程
template <typename  type>   //告诉编译器,下面会用到一个未知类型叫做type
type Max(type a,type b)
{return a>b?a:b;        
}

模板代码

#include <iostream>
using namespace std;
template <typename type> 
type Max(type a, type b) 
{return a > b ? a : b;
}
//typename 可以用class 替换
template <class T>
void print(T data) 
{cout << data << endl;
}int main() 
{//隐式调用cout << Max(1, 2) << endl;cout << Max(1.1, 2.2) << endl;//string 和char* 有区别cout << Max(string("1ILoveyou"), string("2IMissyou")) << endl;//显示调用 <>传类型的参数cout << Max<int>(1, 2) << endl;		//type=int  a=1 b=2cout << Max<string>(string("1"), string("2")) << endl;cout << Max<double>(1.2, 1.3) << endl;return 0;
}

函数模板

函数模板重载问题

  • 函数模板和普通函数

  • 函数模板和函数模板

#include <iostream>
using namespace std;
//No.1 模板与普通函数
int Max(int a, int b) 
{cout << "普通函数..." << endl;return a > b ? a : b;
}
template <class T>
T Max(T a, T b) 
{cout << "模板" << endl;return a > b ? a : b;
}
//No.2 模板与模板
template <class type1,class type2,class type3>
void print(type1 one, type2 two, type3 three) 
{cout << "三只" << endl;
}template <class type1,class type2>				//type1=int type2=double
void print(type1 one, type1 two, type2 tow)     //int int double
{cout << "两只" << endl;
}
template <class type>
void print(type one, type two, type three) 
{cout << "一只" << endl;
}int main() 
{cout << Max<int>(1, 2) << endl;		//显式调用,百分百调用模板cout << Max(1, 2) << endl;			//优先调用类型确定的函数cout << "显示调用" << endl;print<int, double, string>(1, 1.1, string("23"));print<int, double>(1, 1, 1.22);print<int>(1, 2, 3);cout << "隐式调用" << endl;print(1, 1, 2);						//需要传参越少先调用print(1, 1, string("sdsd"));		print(1, 1.11, string("sdsd"));		//只有一种选择return 0;
}

类成员函数是函数模板

//这种不叫做模板类型
class  MM 
{
public:template <class T>void print(T data) {cout << data << endl;}
protected:};
int main()
{MM mm;mm.print(1);mm.print<string>("string");return 0;    
}

函数模板缺省

函数模板缺省和函数参数的缺省是一样的规则

//函数模板缺省
template <class type1,class type2=string>
void printData(type1 one, type2 two) 
{cout << one << endl;cout << two << endl;
}
int main()
{printData<int, double>(1, 1.22);printData<int>(1, string("dsfsdf"));return 0;
}

函数模板传常量

//函数模板传常量
template <class T,size_t size>
void printArray(T* array) 
{for (int i = 0; i < size; i++) {cout << array[i] << " ";}cout << endl;
}
int main()
{int num[3] = { 1,2,3 };printArray<int, 3>(num);//下面代码报错//int length = 3;//printArray<int, length>(num);string str[4] = { "sdds","sd","sdsd" ,"sdds"};printArray<string, 4>(str);return 0;
}

类模板

类模板的基础

  • 怎么写类模板

  • 类模板不是一个完整类型,所以任何用到类名的地方都需要用类名<未知类型>的方式使用

  • 怎么去使用类模板,类模板必须采用显式调用方式

  • 类模板在多文件中不能分开写

  • 可以写在.hpp文件中(声明和实现都在一起)

#include <iostream>
#include <map>
using namespace std;
template <class type1,class type2>
struct my_pair 
{type1 first;		//键type2 second;		//值my_pair(type1 first, type2 second) :first(first), second(second) {}my_pair() = default;
};
template <class type1,class type2>
my_pair<type1, type2> my_make_pair(type1 one, type2 two) 
{return my_pair<type1, type2>(one, two);
}template <class type1,class type2>
class Test 
{
public:Test(type1 one, type2 two) :one(one), two(two) {}void printTest();
protected:type1 one;type2 two;
};
template <class type1, class type2>
void Test<type1,type2>::printTest() 
{cout << one << " " << two << endl;
}template <class type1,class type2>
class Data :public Test<type1,type2> 
{
public:Data(type1 one, type2 two) :Test<type1, type2>(one, two) {}
protected:
};int main() 
{my_pair<int,int> pairData = { 1,2 };cout << pairData.first << " " << pairData.second << endl;my_pair<int, string>* p = new my_pair<int, string>;p->first = 12;p->second = "sdsd";cout << p->first << " " << p->second << endl;Data<int, int>  data(1, 2);data.printTest();//标准库中的pair类型pair<int, string> pD(1, "ILoveyou");cout << pD.first << " " << pD.second << endl;pair<int, string> testData = make_pair<int, string>(1, "sdfsdf");my_pair<int, string> my_testData =my_make_pair<int, string>(1, "sdfsdf");return 0;
}

类模板特化问题

  • 局部特化
  • 完全特化

特化的目的是为了适应不同数据的不同处理

#include <iostream>
using namespace std;
template <class _Ty1,class _Ty2,class _Ty3>
class Data
{
public:Data(_Ty1 one, _Ty2 two, _Ty3 three) :one(one), two(two), three(three) {}void printData(){cout << (one + two + three) << endl;}
private:_Ty1 one;_Ty2 two;_Ty3 three;
};//局部特化
//两个数据,打印两数之差
template <class _Ty1,class _Ty2>
class Data<_Ty1,_Ty1,_Ty2> 
{
public:Data(_Ty1 one, _Ty2 two) :one(one), two(two){}void printData(){cout << (one -two) << endl;}
private:_Ty1 one;_Ty2 two;
};
//只有一个数据,打印数据
template <class _Ty1>
class Data<_Ty1,_Ty1,_Ty1>
{
public:Data(_Ty1 one) :one(one){}void printData(){cout << one << endl;}
private:_Ty1 one;
};//完全特化
template <>
class Data<string, string, string> 
{
public:Data(string one,string two,string three):one(one),two(two),three(three){}void printData();
private:string one;string two;string three;
};
void Data<string,string,string>::printData()
{cout << one << " " << two << " " << three << endl;
}int main() 
{Data<int, int, int> data1(1);data1.printData();Data<int,int, double> data2(2, 1);data2.printData();Data<int, double, float> data3(1, 1.1, 1.2f);data3.printData();Data<string, string, string> data4("dsd","sdfd","sdfdsf");data4.printData();return 0;
}

模板操作自定义类型

模板操作自定义关键点在于重载

#include <iostream>
#include <algorithm>
using namespace std;class MM 
{
public:MM() = default;MM(string name, int age) :name(name), age(age) {}friend ostream& operator<<(ostream& out, const MM& object) {out << object.name << " " << object.age;return out;}
private:string name;int age;
};template <class _Ty>
void printData(_Ty data)
{cout << data << endl;
}template <class _Ty1,class _Ty2,class _Ty3>
class Data
{
public://_Ty1=MM, _Ty2=int, _Ty3=intData(_Ty1 one, _Ty2 two, _Ty3 three) :one(one), two(two), three(three){}void printData() {cout << one << " " << two << " " << three << endl;}
private:_Ty1 one;_Ty2 two;_Ty3 three;
};int main()
{printData(1);printData("string");MM mm = { "小芳",18 };printData(mm);Data<MM, int, int> data(MM("小芳",18),98,99);data.printData();Data<MM, MM, MM> mmData(MM("小芳", 18), MM("小芳", 18), MM("小芳", 18));mmData.printData();return 0;
}

模板嵌套模板

  • 关键点在于大家自己要清楚类型如何表示(类型是由类名<类型>表示一个类型)
#include <iostream>
using namespace std;
template <class _Ty1,class _Ty2,class _Ty3>
class Data 
{
public:Data(_Ty1 one, _Ty2 two, _Ty3 three) :one(one), two(two), three(three) {}void printData() {cout << one << " " << two << " " << three << endl;}friend ostream& operator<<(ostream& out, Data<_Ty1, _Ty2, _Ty3>& object){out << object.one << " " << object.two << " " << object.three;return out;}
protected:_Ty1 one;_Ty2 two;_Ty3 three;
};template <class _Ty1, class _Ty2>
class Info
{
public:Info(_Ty1 one, _Ty2 two) :one(one), two(two) {}void printData(){cout << one << " " << two << endl;}//template <class _Ty1, class _Ty2>  类中实现不需要修饰了,会出现重定义问题friend ostream& operator<<(ostream& out, Info<_Ty1, _Ty2>& object){out << object.one << " " << object.two << " ";return out;}
protected:_Ty1 one;_Ty2 two;};
template <class _Ty1>
class Student
{
public:Student(_Ty1 one) :one(one) {}void printData() {cout << one << endl;}
protected:_Ty1 one;
};int main() 
{Data<int, int, int> data(1,1,1);  //Data<int, int, int>Info<int, int> info(1, 2);		  //Info<int, int>Info<Data<int, int, int>, Data<string, string, string>>test1(Data<int, int, int>(1, 1, 1), Data<string, string, string>("ds", "sd", "sds"));//起别名using type1 = Data<int, int, int>;using type2 = Data<string, string, string>;//别名版本Info<type1, type2>test2(type1(1, 1, 1), type2("ds", "sd", "sds"));Data<Info<int, string>, Info<string, string>, Info<int, double>> test3(Info<int, string>(1,"sd"), Info<string, string>("sdds","dsds"),Info<int, double>(1,1.11));test1.printData();test2.printData();test3.printData();Student<Data<Info<int, int>, Info<int, string>, Info<string, string>>> stu(Data<Info<int, int>, Info<int, string>, Info<string, string>>(Info<int, int>(1,1), Info<int, string>(1,"sdsd"), Info<string, string>("sds","sdsd")));stu.printData();return 0;
}


http://www.ppmy.cn/news/1504160.html

相关文章

【Axure教程】拖拉拽编辑页面

低代码开发平台通常提供拖拉拽编辑页面的功能&#xff0c;使用户无需编写大量代码即可创建复杂的应用程序和页面。这种平台的特点是通过图形用户界面来进行开发&#xff0c;用户可以拖拽组件到画布上进行布局和配置。 那今天作者就教大家在Axure里怎么制作拖拉拽动态编辑页面的…

【Java】解决如何将Http转为Https加密输出

目录 HTTP转HTTPS一、 获取 SSL/TLS 证书二、 安装证书2.1 Apache2.2 Nginx 三、更新网站配置四. 更新网站链接五. 检查并测试六. 自动续期&#xff08;针对 Lets Encrypt&#xff09; HTTP转HTTPS 将网站从 HTTP 转换为 HTTPS 能够加密数据传输&#xff0c;还能提高搜索引擎排…

SQL查询注意事项

判断字符串长度要用函数CHAR_LENGTH(str)&#xff0c;他会返回字符串的长度&#xff0c;如果使用length(str)函数&#xff0c;在对中文字符或特殊字符时&#xff0c;返回的是在当前编码下该字符的字节数。如在mysql中的utf-8编码情况下&#xff0c;length(&#xffe5;)返回结果…

day_30

452. 用最少数量的箭引爆气球 class Solution:def findMinArrowShots(self, points: List[List[int]]) -> int:points.sort(keylambda x:x[0])r points[0][1]cnt 1for i in points:if i[0] > r:cnt 1r i[1]else:r min(r, i[1])return cnt有趣&#xff0c;之前做过的…

3D魔方lua核心脚本制作

制作不易,请好好欣赏 U→R→F→D→L→B 废话不多说,上脚本 --魔方基本运行程序 --星空露珠优化脚本lua --主核心来自分享 --666 --[=[ #G4=I 1 # 2-----------2------------1 # | U1(0) U2(1) U3(2) | # …

Web3时代:科技与物联网的完美结合

随着信息技术的不断进步和物联网应用的普及&#xff0c;Web3技术作为下一代互联网的重要组成部分&#xff0c;正逐渐与物联网技术深度融合&#xff0c;共同开创了新的科技时代。本文将深入探讨Web3技术与物联网的结合&#xff0c;探索它们如何共同推动未来科技发展的新趋势和应…

浅谈ArkTS/ArkUI组件开发

浅谈ArkTS/ArkUI组件开发 本篇文章将从一个移动开发思维的维度出发&#xff0c;浅谈ArkTS组件开发的基础问题&#xff0c;比如状态管理、装饰器、属性传递、自定义构建函数、插槽、条件渲染&#xff0c;模块引用和路由跳转等。 创建项目 这里使用截图简单过一下&#xff0c;不…

星环科技与宁夏银行“大数据联合实验室”揭牌,持续打造金融科技新范式

5月30-31日&#xff0c;2024向星力未来数据技术峰会期间&#xff0c;在峰会现场来宾共同见证下&#xff0c;星环科技与宁夏银行“大数据联合实验室”正式揭牌&#xff0c;宁夏银行股份有限公司首席信息官崔彦刚与星环科技副总裁邱磊共同为联合实验室揭牌。 星环科技与宁夏银行借…