模板:将类型当作未知量,可以忽略类型的影响,从而减少类型对代码的影响
函数模板:
#include<iostream>
#include<string>
using namespace std;
//单个位置类型
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 << endl;
cout << b << endl;
}
int main()
{
int a=Max(1,3);
cout << a << endl;
print(1,2);
print(1.1, 2.1);
}
调用方式:隐式调用 显式调用
函数模板两种形态 普通函数当作模板,类的成员函数当作模板
函数模板的特殊写法:缺省写法,存在常量的写法
#include<iostream>
#include<string>
using namespace std;
template <typename _Ty> //告诉编译器 下面代码用到一个位置类型叫做_Ty
_Ty Max(_Ty a, _Ty b)
{
return a > b ? a : b;
}
//在新标准中 typename_Ty 可以写成class _Ty
template <class _Ty1, class _Ty2>
void print(_Ty1 one, _Ty2 two)
{
cout << one << endl;
cout << two << endl;
}
class Fox
{
public:
template<class _Ty1>
void printf(_Ty1 data=)
{
cout << data << endl;
}
template<class _Ty1>
void printfdata(_Ty1 data);//类中声明
protected:
string name;
int age;
};
//在类外实现不能省略template
template<class _Ty1>
void Fox::printfdata(_Ty1 data)
{
cout << data << endl;
}
//缺省写法
template <class _Ty1,class _Ty2=int >
void printf(_Ty1 a, _Ty2 b)
{
cout << a << b << endl;
}
//常量写法
template <class _Ty1, size_t size=3 >//size_t无符号整形
void printArray(_Ty1 array)
{
for (int i = 0; i < size; i++) {
cout << array[i];
}
cout << endl;
}
void test() //测试函数
{
printf("狐狸",3544);//隐式调用
printf<string>("狐狸", 123);//显式调用,虽有两个未知参数,由于缺省写法,可以少写一个类型,但参数个数不能少
int array[3] = { 0 };
//没有缺省必须显示调用
printArray<int*, 3>(array);
//有了缺省之后可以隐式调用
printArray(array);
//函数模板无法传入变量,函数参数可以
}
int main()
{
//隐式调用
cout << Max(1, 2) << endl;
cout << Max("狐狸1", "狐狸2") << endl;
cout << Max(1.1, 2.3) << endl;
//显示调用
cout << Max<string>("狐狸23", "狐狸24") << endl;
print<string, string>("1", "2");
print<string, int>("1", 1234);
//类中的成员函数是函数模板
Fox fox;
//隐式调用
fox.printf(123);
//显示调用
fox.printf<string>("ILoveyou");
//隐式调用
fox.printfdata(12344);
return 0;
}
类模板:被template修饰就是一个模板类
类模板不是一个实际类,所有用到类名的地方都需要类名<未知类型>方式使用
多文件中,类模板 中的声明和实现一定在一起的,不能分开写。
??
#include<iostream>
#include<string>
using namespace std;
template <class _Ty>
class Fox
{
public:
Fox() {}
Fox(string name) :name(name) {}
void print();
protected:
string name;
};
//在类外实现
template <class _Ty>
void Fox<_Ty>::print()
{
cout << "类模板" << endl;
}
//包括继承中 也要写类名<未知类型>Fox
template<class _Ty>
class Foxson :public Fox<_Ty>
{
public:
Foxson(string name) :Fox<_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 _Ty2,class _Ty1>
void Data<_Ty2, _Ty1>::print()
{
cout << one << endl;
cout << two << endl;
}
int main()
{
//类模板必须显式调用
Foxson<int> foxson("狐狸123");
Data<string, int>data("狐狸1",3);
data.print();
foxson.print();
return 0;
}
自定义类型当作模板参数
自定义类型也是模板,模板传入自定义,关键点在于重载运算符
#include<iostream>
#include<string>
using namespace std;
template <class _Ty>
class Fox
{
public:
Fox() {}
Fox(string name,int age) :name(name),age(age) {}
void print();
friend ostream& operator<<(ostream& out, const Fox& fox) //运算符重载
{
out << fox.name << " " << fox.age;
return out;
}
protected:
string name;
int age;
};
template <class _Ty>
void print(_Ty one)
{
cout << one << endl;
}
int main()
{
print(53);
Fox<string> fox("狐狸1",13);
print(fox);
return 0;
}
#include<iostream>
#include<string>
using namespace std;
class Fox
{
public:
Fox(string name, int age) :name(name), age(age) {}
friend ostream& operator<<(ostream& out, const Fox& fox)//需要运算符重载
{
out << fox.name << " " << fox.age;
return out;
}
protected:
string name;
int age;
};
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<Fox> list;
list.insertList(Fox("狐狸1", 18));
list.insertList(Fox("狐狸2", 13));
list.insertList(Fox("狐狸3", 21));
//将自定义类型当作数据存放进链表
list.printList();
//通过运算符重载输出数据
}
?模板嵌套:
#include <iostream>
using namespace std;
template <class _Ty1, class _Ty2>
class Fox
{
public:
Fox(_Ty1 one, _Ty2 two) :one(one), two(two) {}
friend ostream& operator<<(ostream& out, const Fox& fox)
{
out << fox.one << " " << fox.two;
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 << endl;
}
protected:
_Ty1 one;
_Ty2 two;
};
template <class _Ty>
void print(_Ty data)
{
cout << data << endl;
}
int main()
{
Data<Fox<string, int>, Fox<double, double>>
mData2(Fox<string, int>("狐狸", 13), Fox<double, double>(100.0, 100.0));
//上面一行顶下面4行
Fox<string, int> fox1("狐狸",13);
Fox<double, double>foxscore(100.0,100.0);
Data<Fox<string, int>, Fox<double, double>> mData(fox1, foxscore);
mData.print();
//隐式调用
print(Fox<string, int>("小狐狸", 15));
//显式调用
print<Fox<string, int>>(Fox<string, int>("小狐狸", 21));
//起别名简化代码
using FoxType= Fox<string, int>;
print<FoxType>(FoxType("大狐狸", 3));
}
函数模板的重载
模板和普通函数,调用类型一致的情况下,优先调用普通函数
两个模板都成立,优先相似度高的模板
#include <iostream>
using namespace std;
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()
{
print(15,string("dasdas"));//调用普通函数
print<int, string>(12, "调用两个类型模板");//显示调用百分百调用模板
print(12, string("调用两个类型模板"));
print(12, 12); // 相似度高 调用一个类型
return 0;
}
类模板特化
特化:局部特化 完全特化
#include<iostream>
#include<string>
using namespace std;
template<class _Ty1,class _Ty2 >
//普通类模板
//两个未知类型
class Fox
{
public:
Fox(_Ty1 one, _Ty2 two) :one(one), two(two) {}
void print()
{
cout << one << "" << two << endl;
cout << "原生模板" << endl;
}
protected:
_Ty1 one;
_Ty2 two;
};
class Data
{
public:Data(int a, int b) :a(a), b(b) {};
void printf()
{
cout << a << " " << b << endl;
}
protected:
int a;
int b;
};
//特殊化 ,局部特化,一个未知参数
template<class _Ty >
class Fox<_Ty,_Ty>//产生特化类 类名要用:类型<类名>
{
public:
Fox(_Ty one, _Ty two) :one(one), two(two) {}
void print()
{
one.printf();
two.printf();//针对特殊化数据做特殊化处理
cout << "局部特化" << endl;
}
protected:
_Ty one;
_Ty two;
};
//完全特化
template<>
class Fox<string, string>
{
public:
Fox(string one, string two) :one(one), two(two) {};
void print()
{
cout << one << endl;
cout << two << endl;
cout << "完全特化" << endl;
}
protected:
string one;
string two;
};
int main()
{
Fox<string,int> fox1("小狐狸",3);//原生模板
fox1.print();
Fox<string, string> fox2(string("大狐狸"), string("大大狐狸"));//完全特化
fox2.print();
Fox<Data, Data> dfox(Data(3, 4), Data(8, 9));//局部特化
dfox.print();
}
针对不同的特化进行不同情况下模板的处理
|