模板-C++提高编程

C++的一种编程思想称为泛型编程,用到的技术就是模板

C++提供两种模板:函数模板和类模板。

1.函数模板

1.函数模板作用

建立一个通用函数,其返回值类型和形参类型可以用一个虚拟的类型来代替,提高代码复用性,将类型参数化。

2.语法

template<typename T>
//函数声明或定义

template--声明创建模板

typename--表明其后面的符号是一种数据类型,可以用class代替

T--通用的数据类型,名称可以替换,通常为大写字母

3.例子

未应用模板(代码复杂,通用性差)

void intswap(int& a, int& b)
{
	int c;
	c = a;
	a = b;
	b = c;
}
void doubleswap(double& a, double& b)
{
	double c;
	c = a;
	a = b;
	b = c;
}

应用模板(代码简洁,通用性强)

注意:函数模板一次只能对应一个函数,也就是说T不能多次重复使用

template<typename T>
void swap(T& a, T& b)
{
	T c;
	c = a;
	a = b;
	b = c;
}

4.模板使用方式

1.自动类型推导

swap(a,b);

2.显示指定类型

swap<int>(a,b);

5.注意事项

1.自动类型推导

必须推导出一只的数据类型T才可以使用

反例:

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void swap(T& a, T& b)
{
	T c;
	c = a;
	a = b;
	b = c;
}
int main()
{
	int a=0;
	char b = '12';
	swap(a, b);
	return 0;
}

2.T的类型必须确定

模板必须要确定T的类型,才可以使用

反例:

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void swap()
{
	cout << "swap" << endl;
}
int main()
{
	swap();
	return 0;
}

6.案例

1.题目

对数组进行降序排序

2.代码
#include<iostream>
using namespace std;
#include<string>
template<typename T>
void sort(T a[],int len)
{
	T temp;
	int max ;
	for (int i = 0; i < len; i++)
	{
		max = i;
		for (int j = i; j < len; j++)
		{
			if (a[j] > a[max])
			{
				temp = a[j];
				a[j] = a[max];
				a[max] = temp;
			}
		}
	}
}
int main()
{
	char c[6] = "badce";
	sort(c,5);
	cout << c << endl;
	int a[6] = {4,5,2,3,1};
	sort(a, 5);
	for(int i=0;i<5;i++)
	cout << a[i] << endl;
	return 0;
}
3.结果

7.普通模板与函数模板区别

·普通函数可以发生自动类型转换(隐式类型转换)

·函数模板调用时,如果利用自动类型推导,则不会发生隐式类型转换

·如果利用显示指定类型的方式,可以发生隐式类型转换

1.普通函数隐式类型转换
#include<iostream>
using namespace std;
#include<string>
int fun(int a, int b)
{
	return a + b;
}
int main()
{
	int a = 10;
	char c = 'c';//a=97,c=99
	cout << fun(a, c) << endl;
	return 0;
}

2.自动类型推导不可以使用
#include<iostream>
using namespace std;
#include<string>
template<typename T>
int fun(T a, T b)
{
	return a + b;
}
int main()
{
	int a = 10;
	char c = 'c';
	cout << fun(a, c) << endl;
	return 0;
}

3.显式指定类型可以使用
#include<iostream>
using namespace std;
#include<string>
template<typename T>
int fun(T a, T b)
{
	return a + b;
}
int main()
{
	int a = 10;
	char c = 'c';
	cout << fun<int>(a, c) << endl;
	return 0;
}

4.建议

建议使用显式指定类型的方式调用,这种更加明确。

8.普通函数与函数模板调用规则

1.函数模板可以发生重载
1.普通函数与函数模板重载
#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{
	cout << "函数模板" << endl;
}
void  fun()
{
	cout << "普通函数" << endl;
}
int main()
{
	fun(1);
	fun();
	return 0;
}

2.函数模板之间的重载
#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{
	cout << "函数模板" << endl;
}
template<typename T>
void fun(T a,T b)
{
	cout << "重载函数模板" << endl;
}
int main()
{
	fun(1);
	fun(1, 1);
	return 0;
}
2.调用优先级

如果普通函数和函数模板都可以调用,优先调用函数模板

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{
	cout << "函数模板" << endl;
}
void  fun( int a)
{
	cout << "普通函数" << endl;
}
int main()
{
	fun(1);
	return 0;
}

注意:就算普通函数只有一个声明也不会调用函数模板(会报错)。

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{
	cout << "函数模板" << endl;
}
void  fun(int a);
int main()
{
	fun(1);
	return 0;
}

3.强制调用模板函数

通过空模板参数列表,强制调用函数模板

fun<>(1);
4.发生隐式类型转换时的优先级

当普通函数发生隐式类型转换时,会优先调用函数模板(程序会使用最优选择)

#include<iostream>
using namespace std;
#include<string>
template<typename T>
void fun(T a)
{
	cout << "函数模板" << endl;
}
void fun(char a)
{
	cout << "普通函数调用" << endl;
}
int main()
{
	fun(1);
	return 0;
}

2.类模板

1.定义

建立一个通用类,类中的成员数据类型可以不具体指定,用一个虚拟的类型来代替。

2.语法

template<typename T>
//类

template--声明创建模板

typename--表明其后面的符号是一种数据类型,可以用class代替

T--通用的数据类型,名称可以替换,通常为大写字母

3.例子

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:
	person(A name, B age)
	{
		this->name = name;
		this->age = age;
	}
	void show()
	{
		cout << this->name << this->age << endl;
	}
	A name;
	B age;
};
int main()
{
	person<string, int>p1("孙悟空", 999);
	p1.show();
	return 0;
}

4.类模板与函数模板区别

1.类模板不可以使用自动类型推导,只能自己设置类型。

2.类模板的模板参数列表中可以默认参数

模板参数表:即为尖括号里面的

template<class A,class B>

默认参数

template<class A,class B=int>

5.类模板中的成员函数创建时机

只要不去调用,就不会创建,所以a.fun()不会报错

#include<iostream>
using namespace std;
#include<string>
template<class A>
class person
{
public:
	A a;
	void fun()
	{
		a.fun1();
	}
};
int main()
{
	return 0;
}

6.类模板对象做函数参数

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:
	A name;
	B age;
	person(A name, B age)
	{
		this->name = name;
		this->age=age;
	}
	void show()
	{
		cout << this->name << endl;
		cout << this->age << endl;
	}
};
void fun(person<string, int>&p1)
{
	p1.show();
}
int main()
{
	person<string, int>p1("孙悟空", 100);
	fun(p1);
	return 0;
}

此时的函数参数应该是“person<string, int>&p1”

7.函数模板参数模板化

使用函数模板来提高复用性

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:
	A name;
	B age;
	person(A name, B age)
	{
		this->name = name;
		this->age=age;
	}
	void show()
	{
		cout << this->name << endl;
		cout << this->age << endl;
	}
};
template<class T1,class T2>
void fun(person<T1, T2>&p1)
{
	p1.show();
}
int main()
{
	person<string, int>p1("孙悟空", 100);
	fun(p1);
	return 0;
}

1.类型显示方法

如果想显示出自动类型转换的类型是什么,可以用这个方法

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:
	A name;
	B age;
	person(A name, B age)
	{
		this->name = name;
		this->age=age;
	}
	void show()
	{
		cout <<"姓名:" << this->name << endl;
		cout << "年龄:" << this->age << endl;
	}
};
template<class T1,class T2>
void fun(person<T1, T2>&p1)
{
	p1.show();
	cout <<"T1的类型:" << typeid(T1).name() << endl;
	cout <<"T2的类型:" << typeid(T2).name() << endl;
}
int main()
{
	person<string, int>p1("孙悟空", 100);
	fun(p1);
	return 0;
}

8.将做参数的整个类都模板化

#include<iostream>
using namespace std;
#include<string>
template<class A,class B>
class person
{
public:
	A name;
	B age;
	person(A name, B age)
	{
		this->name = name;
		this->age=age;
	}
	void show()
	{
		cout <<"姓名:" << this->name << endl;
		cout << "年龄:" << this->age << endl;
	}
};
template<class T>
void fun(T &p1)
{
	p1.show();
	cout << "T的数据类型:" << typeid(T).name() << endl;
}
int main()
{
	person<string, int>p1("孙悟空", 100);
	fun(p1);
	return 0;
}

9.类模板与继承

父类如果是一个模板,子类在继承时需要指出他的数据类型

1.手动指定数据类型
#include<iostream>
using namespace std;
#include<string>
template<class T>
class base
{
public:
	T a;
};
class son :public base<int>
{

};
int main()
{
	return 0;
}
2.将子类也变为模板
#include<iostream>
using namespace std;
#include<string>
template<class T>
class base
{
public:
	T a;
};
template<class T1,class T2>
class son :public base<T2>
{
public:
	T1 a;
};
int main()
{
	son<string, int>p1;
	return 0;
}

10.类模板的函数类外实现

1.构造函数的类外实现
#include<iostream>
using namespace std;
#include<string>
template<class T1,class T2>
class person
{
public:
	T1 name;
	T2 age;
	person(T1 name, T2 age);
};
template<class T1,class T2>
person<T1,T2>::person(T1 name,T2 age)
{
	this->name = name;
	this->age = age;
}
int main()
{
	return 0;
}
2.成员函数的类外实现
#include<iostream>
using namespace std;
#include<string>
template<class T1,class T2>
class person
{
public:
	T1 name;
	T2 age;
	person(T1 name,T2 age);
	void fun();
};
template<class T1, class T2>
person<T1, T2>::person(T1 name, T2 age)
{
	this->name = name;
	this->age = age;
}
template<class T1,class T2>
void person<T1, T2>::fun()
{
	cout << name << endl;
	cout << age << endl;
}
int main()
{
	person<string, int>p("埃里给", 18);
	p.fun();
	return 0;
}

11.类模板分文件编写

该程序包含一个头文件和一个源文件,头文件负责函数实现,源文件负责函数调用

.hpp后缀名:约定俗成的包含类模板的声明与实现。

1.头文件(person.hpp)
#pragma once
#include<iostream>
using namespace std;
#include<string>
template<class T1, class T2>
class person
{
public:
	person(T1 name, T2 age);
	void show();
	T1 name;
	T2 age;
};
template<class T1, class T2>
person<T1, T2>::person(T1 name, T2 age)
{
	this->name = name;
	this->age = age;
}
template<class T1, class T2>
void person<T1, T2>::show()
{
	cout << name << endl;
	cout << age << endl;
}
2.源文件
#include"person.hpp"
int main()
{
	person<string,int>p("埃里给", 18);
	p.show();
	return 0;
}
3.输出结果

12.类模板与友元

不想写了,想写的时候补上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值