一.模版函数
1.一般模版函数
如上图,定义了一个交换变量值并打印在控制台的函数模版,通过template预先声明这是一个模版,并在<>内告诉编译器T1,T2是个一般化的变量
2.特化模版函数
与上图代码的区别在于template<>内不声明如T1,T2这样的一般化变量,这也就意味着特化模版函数内的参数必须全部指定
学到这里的时候我感觉十分困惑,因为这样一来特化模版函数与普通函数似乎不存在区别
百度的结果也告诉我大部分时候它们的作用是差不多的,只是同名的特化模版函数与普通函数可以同时存在而不会发生重定义,并且编辑器会优先调用普通函数(因为只有确定需要使用模版函数时它才会被生成),这种现象有点类似于重载
https://bbs.csdn.net/topics/330199640
二.模版类
1.类模版
模板类实际上是建立一个通用的类模板后实例化出的类。其数据成员、成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表,只有使用类模版定义对象后,编辑器才会将实际的类型取代其虚拟的类型
#include#include using namespace std; template class Li { public: T1 a; T1 b; T2 a_name; T2 b_name; Li(T1 a,T1 b,T2 a_name,T2 b_name){ this->a=a; this->b=b; this->a_name=a_name; this->b_name=b_name; } bool maxT(); }; template bool Li ::maxT() { if(a>b){ cout<"< 可以看出,在template声明T后,整个类内都可以使用,如果在类的外部书写其的函数,则前面也要加上相同的template声明,且类名后要加
与声明一致,否则经实测编译器会报错(哪怕实际上该类外函数不需要用到这么多不同变量) 类模版stack举例:
#includeconst int size=10; template //模板声明,其中T为类型参数 class Stack{ //类模板为Stack public: void init() { tos=0; } void push(T ob); //声明成员函数push的原型,函数参数类型为T类型 T pop(); //声明成员函数pop的原型,其返回值类型为T类型 private: T stack[size]; //数组类型为T,即是自可取任意类型 int tos; }; template //模板声明 void Stack ::push(T ob) //在类模板体外定义成员函数push { if(tos==size) { cout<<"Stack is full"< //模板声明 T Stack ::pop() //在类模板体外定义成员函数push { if(tos==0) { cout<<"Stack is empty"< s1; //用类模板定义对象s,此时T被char取代 s1.init(); s1.push('a'); s1.push('b'); s1.push('c'); for(int i=0;i<3;i++){cout<<"pop s1:"< s2; //用类模板定义对象s,此时T被int取代 s2.init(); s2.push(1); s2.push(3); s2.push(5); for(int i=0;i<3;i++){cout<<"pop s2:"< 2.成员模版函数
class Printer { public: templatevoid p(T pri) { cout << pri < test(18,19,"Aa","Bb"); //int m=test.maxT(); //cout< 3.模版特化
(1)模版成员函数特化
class Printer { public: templatevoid p(T pri) { cout <<"T:"< void Printer::p (int pri){ cout <<"int:"< test(18,19,"Aa","Bb"); //int m=test.maxT(); //cout< (1); return 0; } 实测中共三点需要注意:
one
在类内定义了成员函数模版后,必须在类外声明特化函数的template<>,否则会报错
two
定义了成员函数模版和特化后,使用该函数时后面必须要写<>并给其指定参数类型,而不能省略
如果该参数类型下有特化函数,则优先使用特化函数,否则调用模版函数(如上面代码,指定int时优先调用特化函数,指定double时因为没有特化函数所以用模版函数)
three
特化函数中<>内指定的参数类型在特化函数中的使用必须与模版函数对应的T在模版函数中的使用相对应
如上面T特化为int后,在该特化函数中原本输入的T必须变为int,不能这样写:
void Printer::p
(string pri){ (2)模版类特化
templateclass Printer { public: //template void p(T pri) { cout <<"T:"< class Printer { public: //template void p(int pri) { cout <<"T:"< test(18,19,"Aa","Bb"); //int m=test.maxT(); //cout< p; p.p(1); return 0; } 三.模版类(autoPtr)
构造函数
autoPtr(T n) { ptr = new T;//去掉T*,直接用Private里T*好的ptr *ptr = n; cout << "new pointer created." << endl; cout << *ptr << endl; //这个地方可以输出ptr指向的值 }析构函数
~autoPtr()拷贝构造函数
SmartPointer(const SmartPointer& obj) //重新实现拷贝构造函数 { m_pointer = obj.m_pointer; const_cast &>(obj).m_pointer = NULL; } 运算符重载
T* operator ->() //重载->操作符 { return m_pointer; } T& operator *() //重载*操作符 { return *(m_pointer); }主函数
int main() { { SmartPointerp1 = new int(12); //指向一个int堆变量 cout << "(*p1) = " << (*p1) << endl; SmartPointer p2 = p1; cout << "p1.isNull() = " << p1.isNull() << endl; cout << "*p2.get() = " << *p2.get() << endl; SmartPointer pt = new Test; //指向一个Test堆对象 } return 0; } 智能指针的实现原理就是资源分配,它定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。智能指针的实现机制就是利用类的构造和析构函数(释放资源)是由编译器自动调用的。



