C++模板

函数模板

什么是模板:

把类型当作未知量来处理,可以忽略类型的影响。

申明模板方法:template<typename 类型代号>

存在多个未知数据类型template<typename 类型代号,typename 类型代号>

其中typename可以换成class

tmplate<class 类型代号>

调用函数模板:

隐式调用:正常函数传参即可调用

显示调用 :函数名<类型名>(参数)

函数模板的两种形态:

1.普通函数当作模板

2.类的成员函数是函数模板

函数模板特殊写法:

1.缺省写法

2.存在一个常量类型

#include<iostream>
using namespace std;
//int Max(int a, int b) {
//	return a > b ? a : b;
//}
//string Max(string a, string b) {
//	return a > b ? a : b;
//}
//引入模板概念template

template <typename _Ty>//标准格式
_Ty Max(_Ty a, _Ty b) {
	return a > b ? a : b;
}
template<class _Ty1, class _Ty2>void print(_Ty1 a, _Ty2 b) {
	cout << a << endl;
	cout << b << endl;
}
//类的成员函数是函数模板
class Girl {
public:
	template<class _Ty>void print(_Ty data) {
		cout << data << endl;
	}
	template<typename _Ty>void printData(_Ty data);
protected:
	string name;
	int age;
};
template<typename _Ty>void Girl::printData(_Ty data) {//类中申明,类外实现前缀不能省略
	cout << data << endl;
}
//缺省写法
template<class _Ty1, class _Ty2 = int>void printData(_Ty1 one, _Ty2 two) {
	cout << one << "\t" << two << endl;
}
//存在传常量写法
template<class _Ty1, size_t size>void printArray(_Ty1 array) {//_Ty1=int*,size=3(必须显示调用,除废用缺省)
	for (int i = 0; i < size; i++) {
		cout << array[i];
	}
	cout << endl;
}	//size_t无符号整形的别名
void testFunc() {
	printData("string", 1231);
	//可以类型缺省,但是参数不能少
	printData<string>("string", 123);
	int array[3] = { 1,2,3 };
	printArray<int*,3>(array);
	
	/*int size = 3;//不能传变量,只能传入常量,函数模板如果存在变量的情况下
	printArray<int*,size>(array)*/
}
int main() {
	cout << Max(1, 2) << endl;//隐式调用
	cout << Max("string1", "string2") << endl;//隐式调用
	cout << Max(1.1,2.5) << endl;//隐式调用
	
	cout << Max<string>("abc", "def") << endl;//显示调用

	print<string, string>("1234", "4321");
	print<string, int>("1234", 4321);
	
	

	//调用类中成员函数模板
	Girl girl;
	girl.print(123);
	girl.print<string>("ILoveYou");
	//模板函数也可以缺省
	return 0;
}

类模板(用在数据结构上比较多)

如何生成一个类模板:

template<class _Ty>class MM{

public:

protected:

}

只要被template修饰了就是模板类型,至于是否用了未知类型,没有关系

类模板的调用:

必须采用显示调用

类模板不是一个实际的类,所以所有用到类名的地方,都需要使用类名<未知类型>方式使用

多文件中,类模板中的声明和实现一定是在一起的,不能分开写。

和函数模板一样可以传常量

#include<iostream>
using namespace std;
//template<>class Data {
//public:
//protected:
//};
template<class _Ty>class MM {
public:
	MM(){}//构造函数正常写
	MM(string name):name(name){}
	void print();
protected:
	string name;
};
//在类外实现
template<class _Ty>void MM<_Ty>::print() {
	cout << "类模板" << endl;
}
//继承
template<class _Ty>class Girl :public MM<_Ty> {
public:
	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;
	cout << two << endl;
}
int main() {
	//MM mm;模板类直接创建对象报错
	//必须采用显示调用
	MM<int>mm1;
	MM<string>mm2;
	Girl<int> girl("loveyou");
	Data<string, int> data1("张三", 20);
	data1.print();
	Data<int, int> data2(12, 21);
	data2.print();

	return 0;
}

 模板传入自定义类型

 基本自定义类型:

自定义类型也是模板:

模板传入自定义类型,关键点就在运算符重载

#include<iostream>
using namespace std;

class MM {
public:
	MM(string name,int age):name(name),age(age){}
	friend ostream& operator<<(ostream& out,const MM& mm) {
		out << mm.name << " " << 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){
// 二元"<<":没有找到接受“_Ty”类型的右操作数的运算符(或没有可接受的转换)
	//对象不能直接打印
	cout << one << endl;
}
template<class _Ty>_Ty Max(_Ty a,_Ty b) {
	return a > b ? a : b;
}

template <class _Ty> class Node {
	//using LPtype = Node<_Ty>;
public:
	Node(_Ty data,Node<_Ty>* next):data(data),next(next){}
	Node<_Ty>* getNext() {
		return next;
	}
	_Ty getData() {
		return data;//MM对象返回值是常属性,所以<<重载要加const!!!!
	}
protected:
	_Ty data;
	//LPtype* next;
	Node<_Ty>* next;
};
template<class _Ty>class List {
public:
	
	List() {
		headNode = nullptr;
	}
	void insertList(_Ty data) {
		headNode = new Node<_Ty>(data, headNode);
	}
	void printData() {
		Node<_Ty>* pMove = headNode;
		while (pMove != nullptr) {
			cout << pMove->getData() << endl;
			pMove = pMove->getNext();
		}
	}
protected:
	Node<_Ty>* headNode;
};
void testList(){
	List<int> list;
	list.insertList(1);
	list.insertList(2);
	list.insertList(3);
	list.printData();
	List<MM> mmList;
	mmList.insertList(MM("小花", 21));
	mmList.insertList(MM("小华", 12));
	mmList.insertList(MM("晓华", 32));
	mmList.printData();
}
int main() {
	//函数模板传入自定义类型
	print<int>(12);
	print("Ilobeyou");
	print(MM("mm", 19));
	
	MM girl1("张三", 21);
	MM girl2("李四", 25);
	MM result = Max<MM>(girl1, girl2);//也可以隐式调用
	cout << result;

	testList();
	return 0;
}

模板的嵌套(类)

明白类型是什么即可,可以适当运用using语法起别名,简化代码。

#include<iostream>
using namespace std;

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;
		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: 
	//MM<_Ty1, _Ty2> mmData;
	_Ty1 one;
	_Ty2 two;
};
void testFunc() {
	//_Ty1类型是MM
	//_Ty类型是MM<string,double>
	Data<MM<string, int>, MM<string, double>> data(MM<string,int>("小强",18),MM<string,double>("大强",20.0));
	data.print();
}

template<class _Ty>void print(_Ty data) {
	cout << data << endl;
}

int main() {

	print(MM<string, int>("晓华", 12));
	print<MM<string, int>>(MM<string, int>("张三", 40));
	using MMType = MM<string, int>;
	print<MMType>(MMType("李四", 28));

	testFunc();
	return 0;
}

函数模板重载

#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<int, string>(12, "显示调用一定调用模板的");
	print(21, string("优先调用适应的普通函数"));
	//当两个模板同时成立,优先调用类型相似度高的那个
	print(12, 12);

	return 0;
}

类模板特化

局部特化:

完全特化:

#include<iostream>
#include<string>
using namespace std;
//两个未知类型
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 Data {
public:
	Data(int a,int b):a(a),b(b){}
	void print() {
		cout << a << " " << b << endl;

	}
protected:
	int a;
	int b;
};

//局部特化,特殊化
template<class _Ty>class MM<_Ty,_Ty> {//特化产生的类,类名要用:类名<类型>方式使用
public:
	MM(_Ty one, _Ty two) :one(one), two(two) {}
	void print() {
		//cout << one << " " << two << endl;
		one.print();
		two.print();
		cout << "特殊化" << endl;
	}
protected:
	_Ty one;
	_Ty two;
};

//完全特化(类型全部具体化)
//在折叠参数中有用
template<>class MM<string, string> {
public:
	MM(string one,string two):one(one),two(two){}
	void print() {
		cout << "完全特化" << endl;
		cout << one << " " << endl;
	}
protected:
	string one;
	string two;
};
int main() {
	MM<string, int>mm1("张三", 48);
	//MM<string,string>mm2("李四","翠花");
	MM<Data, Data> dMM(Data(1,2),Data(3,4));
	dMM.print();

	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值