C++基础-模板

C++基础-模板,第1张

模板

模板并不是一个实在的类或函数,它们仅仅是逻辑功能相同而类型不同的函数和类的一种抽象,是参数化的函数和类。

1、函数模板

将逻辑功能相同而函数参数和函数值类型不同的多个重载函数用一个函数来描述。
函数模板可以用来创建一个通用功能的函数,以支持多种不同的形参,进一步简化重载函数的函数体设计。
定义形式:

template
返回类型 函数名(形参表)
{
函数体;
}

例如,将add函数定义成一个函数模板:

template<class T>
T add(T x,T y)
{
	return x+y;
}

函数模板定义后,就可以用它生成各种具体的函数,称为模板函数。
在函数调用时,用函数模板生成模板函数实际上就是模板参数表中的参数化类型根据实参实例化成具体类型,这个过程称为模板的实例化
显式实例化:

函数名<具体类型名1,具体类型名2,……,常量表达式>(实参表)

隐式实例化:
格式为函数调用式,实例化过程是在实参与形参结合时用实参的类型实例化形参对应的参数化类型。
使用隐式实例化无法初始化模板参数表中的普通类型的形参,要使用显式初始化。

#include
using namespace std;
//定义函数模板
template<class T1,class T2>
T1 add(T1 x,T2 y)
{
    cout<<"("<<sizeof(T1)<<","<<sizeof(T2)<<")\t";
    return x+y;
}
int main()
{
    //隐式实例化
    cout<<add(1,2)<<endl;
    cout<<add(1.2,2.0)<<endl;
    cout<<add(1,2.0)<<endl;
    cout<<add('a','A'-'0')<<endl;
    cout<<add(long(8),9)<<endl;
    return 0;
}

当同时存在函数重载和函数模板时,先进行函数重载的精准匹配,否则实例化函数模板。

2、类模板

就是带有类型参数的类,能根据不同的参数建立不同类型成员的具体类,称为类的实例化,
类模板的定义:

template<模板参数表>
class 类名
{
成员名;
};

例如定义一个模板类Student:

template<class TNO,class TScore,int num>
class Student
{
    private:
        int n;
        //参数化类型,StudentId可以实例化成字符串、整型数组等
        TNO StudentId[num];
        TScore score[num];
    public:
        student();
        void append(TNO id,TScore s);
        void dispall();

};

模板类的成员函数可以在类外定义:

template<模板参数表>
类型 类名 <模板参数名表>::函数名(参数表)
{
函数体;
}

  • 模板参数表与类模板的模板参数表相同;
  • 模板参数名表列出的是模板参数表中的参数名,顺序要保持一致。

类模板实例化(显式方式):

类模板名<模板参数值表>对象名1,对象名2,……;

  • 模板参数值表的值为类型名,可以是基本数据类型,也可是构造数据类型,还可是类类型名;
  • 模板参数值表的值可以是常数,以初始化普通参数;
  • 模板参数值表的值必须按一一对应的顺序实例化类模板的模板参数表。

默认模板参数:
类模板的类型参数可以采用默认值,这样就避免了每次实例化时都显式给出参数。

template<class TNO, class TScore=int, int num=100>
.....
//实例化时可以写成:
Student<long>students;//这样TScore默认为int,num默认为100

例子:创建学生类模板并实例化,用于管理学生成绩

#include 
using namespace std;

template<class TNO, class TScore, int num>
class Student {
	private:
		static int n;//实际人数,设置为静态数据成员,类内定义
		TNO StudentId[num];//学生学号
		TScore score[num];//学生成绩
	public:
		void append(TNO id, TScore s);//添加学生
		void del(TNO id);//删除
		int search(TNO id);//查找
		void sort();//根据成绩排序
		void display();//显示学生学号及成绩
		Student() {};//默认构造函数
};
//类外初始化静态数据成员
template<class TNO,class TScore,int num>

int Student<TNO,TScore,num>::n=0;

template<class TNO, class TScore, int num>

void Student<TNO, TScore, num>::append(TNO id, TScore s) {
	if (n < num) {//不能超过总数量
		StudentId[n] = id;
		score[n] = s;
		n++;
	}
}
template<class TNO, class TScore, int num>

void Student<TNO, TScore, num>::del(TNO id) {
	for (int i = 0; i < n; i++) {
		if (StudentId[i] == id) {//找到
			for (int j = i; j < n; j++) {
				StudentId[j] = StudentId[j + 1];//前移一位,即可删除
				score[j] = score[j + 1];
			}
			n--;//总人数-1
		}
	}
}
template<class TNO, class TScore, int num>

int Student<TNO, TScore, num>::search(TNO id) {
	for (int i = 0; i < n; i++) {
		if (StudentId[i] == id) {
			return i + 1; //找到,第几个
		}
	}
	return -1;//未找到
}
template<class TNO, class TScore, int num>

void Student<TNO, TScore, num>::sort() {
	for (int i = 0; i < n - 1; i++) {
		for (int j = i + 1; j < n; j++) {
			if (score[i] < score[j]) {//按成绩降序排序(选择排序)
				TScore ts;
				TNO tn;//建立临时对象
				//交换
				ts = score[i], tn = StudentId[i];
				score[i] = score[j], StudentId[i] = StudentId[j];
				score[j] = ts, StudentId[j] = tn;
			}
		}
	}
}
template<class TNO, class TScore, int num>

void Student<TNO, TScore, num>::display() {
	for (int i = 0; i < n; i++) {
		cout << StudentId[i] << "\t" << score[i] << endl;
	}
}

int main() {
	Student<long, int, 100>students;//实例化类模板
	students.append(001, 80);
	students.append(002, 90);
	students.append(003, 85);
	students.sort();
	students.display();
	int pos = students.search(002);
	cout << pos << endl;
	students.del(001);
	students.display();
	
	return 0;
}
2       90
3       85
1       80
1
2       90
3       85

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1325321.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-12
下一篇2022-06-12

发表评论

登录后才能评论

评论列表(0条)

    保存