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=2
cout << 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=int
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;
};
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;
}
发表评论