模板c++
2022/1/28 14:04:18
本文主要是介绍模板c++,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录
一、模板简介
1、调用函数模板 隐式调用:正常函数传参即可调用 显示调用:函数名<类型名>(参数)
2、函数模板的两种形态:
(1)、 普通函数函数模板 (2) 、类中函数函数模板
3、函数模板特殊写法:(1)缺省写法 (2)存在常量类型写法
二、类模板
三、自定义类型做模板
四、模板的嵌套
五、类模板的特化
局部特化
完全特化
六、函数模板的重载
一、模板简介
函数模板
模板:把类型作为未知量
声明模板的语法 template<typename _Ty> 注:_Ty只是代号可以替换
(1)引入模板
typename可以替换为class 如可以改写为template<class T>
//实际上两句为一句,只是为了好看才这样写 //template<typename _Ty> _Ty Max(_Ty a, _Ty b) template<typename _Ty>//下面代码用到未知类型_Ty _Ty Max(_Ty a, _Ty b) { return a > b ? a : b; } //多模板 template<typename _Ty1,typename _Ty2> void print( _Ty1 a, _Ty2 b) { cout << a << b << endl; }
1、调用函数模板
隐式调用:正常函数传参即可调用
显示调用:函数名<类型名>(参数)
//使用的就是上面的函数 //隐士调用 cout << Max(1, 2) << endl; cout << Max("s", "sad") << endl; //显示调用 注意类型的匹配 cout << Max<string>("as", "sd"); print<string, string>("asa", "fd");
2、函数模板的两种形态:
(1)、 普通函数函数模板 (2) 、类中函数函数模板
普通函数模板就是之前的例子,下面的是类中函数模板
注:类外实现要写完整
class MM { public: template<class _Ty> void print(_Ty data) { cout << data; }//本质就是一行 为了好看会把代码拆开来 类外实现要写写全 template <class _Ty>void printData(_Ty data); }; template <class _Ty>void MM::printData(_Ty data) { cout << data; } //隐式调用 MM mm; mm.printData(1234);
3、函数模板特殊写法:(1)缺省写法 (2)存在常量类型写法
(1)缺省写法
template<typename _Ty1, typename _Ty2=int> void print2(_Ty1 one, _Ty2 two) { cout << one << "\t" << two << endl; } int main() { //缺省:可以不传类型 但参数不可少 //函数模板显示调用 print2<string>("as", 123); print2("123", 123); return 0; }
(2)存在传常量情况 不能传变量只能传常量
做了缺省可以隐式调用 否则必须显示调用
template<class _Ty1,size_t size>//size_t无符号整形别名 void printArray(_Ty1 array) { for (int i = 0;i < size;i++)//size可以直接使用 { cout << array[i]; } } int main() { //存在传常量的情况 做了缺省可以隐式调用 否则必须显示调用 int array[3] = { 1,2,3 }; printArray<int*,3>(array); return 0; }
二、类模板
声明:template<class _Ty>
class MM{};
只要被修饰了就是模板类,不管有没有使用位置未知类型
类模板的调用(类外实现,继承,子类构造函数)
必须要显示调用
类模板不是一个实际类型,所以所有用到类名的地方都要使用:类名<未知类型>方法使用
多文件中,类模板的声明和实现要在一起,不能分开写
注意:1类外实现的写法变为了MM<_Ty>::
2继承的时候给父类赋值的写法
3 定义对象的写法
template<class _Ty> class MM//准备一个父类 { public: MM() {} MM(string name):name(name) {} void print(); protected: string name; }; template<class _Ty> void MM<_Ty>::print()//注意这里的声明变为了MM<_Ty>:: { cout << "类模板" << endl; } //子类 template<class _Ty> class Girl :public MM<_Ty> { public://子函数构造函再给父类赋值时需要加<_Ty> Girl(string name) :MM<_Ty>(name) {} protected: };
template<class _Ty1,class _Ty2> class Data { public: Data(_Ty1 one, _Ty2 two) :one(one), two(two) {} void print(); protected: _Ty1 one; _Ty2 two; }; template<class _Ty1, class _Ty2> void Data<_Ty1, _Ty2>::print() { cout << one << endl << two << endl; }
调用
int main() { //必须采用显示调用 MM<int> mm; Girl<int> g("adas"); g.print(); Data<string, int> n("qwe", 21); n.print(); return 0; }
三、自定义类型做模板
关键在于运算符的重载
//准备一个数据类
class MM { public: MM(string name, int age) :name(name), age(age) {} friend ostream& operator<<(ostream& out,const MM& mm) { out << mm.name << "\t" << mm.age << endl; return out; } bool operator > (MM& mm)const { return this->age>mm.age; } protected: string name; int age; };
template<class _Ty> void print(_Ty one) { cout << one; } template<class _Ty> _Ty Max(_Ty a, _Ty b) { return a > b ? a : b; } int main() { //函数模板传入自定义类型 print(MM("asds", 123)); MM x("asd", 13); MM s("qwe", 17); MM result=Max(x, s);//Max<MM>() cout << result; return 0; }
以链表为例存入自定义数据类型的数据
//类模板 template<class _Ty> class Node { public: Node(_Ty data, Node<_Ty>* next) :data(data), next(next) {} _Ty getData() { return data; } Node<_Ty>* getNext() { return next; } protected: _Ty data; Node<_Ty>* next; }; template<class _Ty> class List { public: List() { headNode = nullptr; } void insertList(_Ty data) { headNode = new Node<_Ty>(data, headNode); } void printList() { Node<_Ty>* pMove = headNode; while (pMove != nullptr) { cout << pMove->getData() << endl; pMove = pMove->getNext(); } cout << endl; } protected: Node<_Ty>* headNode; };
调用·
int main() { List<int> list; list.insertList(1); list.insertList(2); list.printList(); //这里的MM就是一开始准备的数据类,其中<<在MM类中做了运算符重载 List<MM> list1; list1.insertList(MM("as", 12)); list1.insertList(MM("qw", 16)); list1.printList(); return 0; }
四、模板的嵌套
//准备两个类模板MM和Data template<class _Ty1,class _Ty2> class MM { public: MM(_Ty1 one, _Ty2 two) :one(one), two(two) {} friend ostream& operator<<(ostream& out, const MM& mm) { out << mm.one << " " << mm.two << endl; return out; } protected: _Ty1 one; _Ty2 two; }; template<class _Ty1, class _Ty2> class Data { public: Data(_Ty1 one, _Ty2 two) :one(one), two(two) {} void print() { cout << one << two; } protected: _Ty1 one; _Ty2 two; }; template<class _Ty> void print(_Ty data) { cout << data << endl; } int main() { //隐士调用 print(MM<string, int>("asd", 123)); //显示调用 print<MM<string, int>>(MM<string, int>("asd", 123)); Data<MM<string, int>, MM<double, int>>//显示调用 data(MM<string, int>("ASD", 123), //定义data并赋值 MM<double, int>(12.3, 12)); data.print(); return 0; }
五、类模板的特化
初始的类模板
template<class _Ty1,class _Ty2> class MM { public: MM(_Ty1 one, _Ty2 two) :one(one), two(two) {} void print() { cout << one << " "<<two << endl; } protected: _Ty1 one; _Ty2 two; };
局部特化
两个未知类型变为一个未知类型 称为局部特化或特殊化
特殊化(针对特殊化数据特殊化处理) 如传入对象在打印时更改打印方式调用方法
注意写法:特化产生的类类名要用:类名<类型>方式使用
class MM<_Ty,_Ty> //特化产生的类类名要用:类名<类型>方式使用 { public: MM(_Ty one, _Ty two) :one(one), two(two) {} void print() { one.print(); two.print(); } protected: _Ty one; _Ty two; }; class Data { public: Data(int one, int two) :one(one), two(two) {} void print() { cout << one << "特殊化 " << two << endl; } protected: int one; int two; }; int main() { MM<Data, Data> mm3(Data(1, 2), Data(2,3)); mm3.print(); return 0; }
完全特化 依旧是模板类 类型变为已知 元组容器
template<> class MM<string, string> { public: MM(string one, string two) :one(one), two(two) {} void print() { cout << one << "完全特化 " << two << endl; } protected: string one; string two; }; int main() { MM<string, string> mm4("sad", "zxc"); mm4.print(); return 0; }
六、函数模板的重载
隐士调用优先调用类型一致的函数
字符传优先解析为char*
隐士调用中当2个模板同时成立,优先调用类型相似度高的
void print(int a, string b) { cout << "普通函数" << endl; } template <class _Ty1,class _Ty2> void print(_Ty1 a, _Ty2 b) { cout << "两个类型" << endl; } template<class _Ty> void print(_Ty a, _Ty b) { cout << "一个类型 " << endl; } int main() { //显示调用 100%调用模板 //隐士调用优先调用类型一致的函数 //字符传优先解析为char* print(12, string("qwe")); print(12, "qwe"); //隐士调用中当2个模板同时成立,优先调用类型相似度高的 print(12, 12); }
这篇关于模板c++的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享