C++学习笔记(一)函数模板与类模板

本文深入探讨了C++中函数模板和类模板的概念与应用,通过实例展示了如何使用模板简化代码,提高复用性,并介绍了模板特化、非类型模板参数以及如何在实际编程中有效利用这些特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

本文讲解了C++函数模板和类模板的相关知识,当需要多个函数对多个不同的数据类型的数据进行相同的处理时,需要多次重载函数,而使用函数模板,编译器产生不同的目标代码函数来适当地处理每个函数的调用,显得更加简便。将这一概念引入至类中,将类中数据成员的类型都参数化(把数据类型定义为参数),在初始化类对象的时候,根据实参确定数据类型。

二、函数模板

当需要函数用于执行相似的操作,这些操作处理不同数据类型上的相同程序逻辑,即函数要处理的数据类型不同,但程序逻辑一样,那么使用函数模板可以简便地对函数进行重载,而不用进行多次重载。

例如求最大值的函数maximum(),如果要对int、float或double型的3个变量求出最大值,那么将要重载函数2次以上,而使用函数模板可以使程序更简洁。

#include <iostream>
using namespace std;

template<class T>     //表示下面为一函数模板
T maximum( T value1 ,T value2 ,T value3)
{
	T maximumValue = value1;
	if (value2 >maximumValue)
		maximumValue = value2;
	if(value3 >maximumValue)
		maximumValue = value3;
	return maximumValue;
}

int main()
{
	int i1,i2,i3;
	cout<<"Input three integer values: ";
	cin>>i1>>i2>>i3;
	cout<<"The maximum integer value is: "
		<<maximum(i1 ,i2,i3)<<endl;

	double d1,d2,d3;
	cout<<"Input three double values: ";
	cin>>d1>>d2>>d3;
	cout<<"The maximum double value is: "
		<<maximum(d1 ,d2,d3)<<endl;

	char c1,c2,c3;
	cout<<"Input three characters values: ";
	cin>>c1>>c2>>c3;
	cout<<"The maximum characters value is: "
		<<maximum(c1 ,c2,c3)<<endl;
	return 0;
}


函数模板的声明为

template < typename T>  //尖括号可以有多个形参

或者是

template < class T>      

或者是

template<>表示下面为一模板函数,尖括号中class或typename(两者区别不大),说明后面的一个字符T(也可以用其他符号)是表示一个类型(可为int、float、结构体等),接下来函数定义中则使用T作为一种泛型类型,可作为返回值类型,或函数形参的类型。

如上文的T maximum( T value1 ,T value2 ,T value3)

三、类模板

类模板的声明及定义如下:

template <typename或class T>

class 类名

{

       //具体定义…..

}

其中template<>中的形参可以多个

例子如下:

//TemplateClass.h
#ifndef TemplateClass_H
#define TemplateClass_H

#include <iostream>
using std::cout;
using std::endl;

template< typename T1 ,typename T2 >
class ClassA
{
public:
	ClassA(T1 ,T2);   
	void print();
private:
	T1 a;
	T2 b;
};

#endif

template< typename T1 ,typename T2 >    //注意再每个函数头前均有此声明语句
ClassA<T1,T2>::ClassA(T1 v1 ,T2 v2 )    //构造函数
	:a(v1),b(v2)
{

}

template< typename T1 ,typename T2 >
void ClassA<T1,T2>::print()             //print函数
{
	cout<<a<<" "<<b<<endl;
}

//main.cpp
#include "TemplateClass.h"

int main()
{
	ClassA<char,int> a('a',1);
	a.print();
	return 0;
}

可看出该类的成员函数均为模板函数,在main函数中初始化类对象时,编译器将根据实参类型确定T1,T2的类型。

四、模板特化

如果我们想给模板函数(或类模板)实现一个已确定数据类型的函数,那么可以才用模板特化,当遇到该类数据类型的数据时,则调用该模板特化。特化分为全特化和偏特化,函数模板只有全特化,类模板有全特化和偏特化。

(1)函数模板特化

在前面提到的求最大值的函数maximum(),现在针对int类型写一模板特化如下:

template<>     //表明下面是一个模板函数,由于针对int型,尖括号内省去
int maximum( int value1 ,int value2 ,int value3)
{
	int maximumValue = value1;
	if (value2 >maximumValue)
		maximumValue = value2;
	if(value3 >maximumValue)
		maximumValue = value3;
	cout<<value1<<"+"<<value2<<"+"<<value3    //
		<<"="<<value1+value2+value3<<endl;    //增加求三者之和
	return maximumValue;
}

则当传入maximum()的实参均为int型时,程序优先调用该程序,结果


(2)类模板特化

类模板有2种形式,全特化和偏特化,先介绍全特化,在上面类模板的讲解中,将TemplateClass.h头文件中的ClassA类分别全特化、偏特化,代码如下:

//TemplateClass.h
#ifndef TemplateClass_H
#define TemplateClass_H

#include <iostream>
using std::cout;
using std::endl;

typedef struct point
{
	double x;
	double y;
};


template< typename T1 ,typename T2 >
class ClassA
{
public:
	ClassA(T1 v1,T2 v2):a(v1),b(v2){};
	void print()
	{
			cout<<a<<" "<<b<<"\n\n";;
	}
private:
	T1 a;
	T2 b;
};

#endif

template<>        //将ClassA类全特化,即将T1,T2确定为结构体point类型
class ClassA<point ,point>
{
public:
	ClassA(point p1,point p2):a(p1),b(p2){};
	void print()
	{
		cout<<a.x<<" "<<a.y<<endl;
		cout<<b.x<<" "<<b.y<<"\n\n";;
	}
private:
	point a;
	point b;
};

template<typename T2 >        //将ClassA类偏特化,只将T1确定为结构体point类型,T2不特化
class ClassA<point ,T2>
{
public:
	ClassA(point p1,T2 v2):a(p1),b(v2){};
	void print()
	{
		cout<<a.x<<" "<<a.y<<endl;
		cout<<b<<"\n\n";
	}
private:
	point a;
	T2 b;
};

//main.cpp
#include "TemplateClass.h"

int main()
{
	ClassA<char,int> a('a',1);   //调用类模板
	a.print();

	point p1;                    
	point p2;
	p1.x = 0.1;
	p1.y = 0.2;
	p2.x = 1.1;
	p2.y = 1.2;
	ClassA <point,point> b(p1,p2);    //调用类模板全特化
	b.print();

	ClassA<point ,int> c(p1 ,1);      //调用类模板偏特化
	c.print();
	return 0;
}

结果


五、非类型模版参数

非类型模板参数指定是在函数模板(或类模板)中,模板template<>,尖括号中的参数除了typename T(类型),还可增加常整数(包括枚举)或者指向外部链接对象的指针,浮点型float和类对象是不允许作为非类型模板参数的。示例如下:

template<typename T ,int MAXSIZE>
class ClassB
{
public:
	ClassB()
	{
		for(int i=0;i<MAXSIZE ;i++)
			elem[i] =i+1;
	}
	void print()
	{
		for(int i=0;i<MAXSIZE ;i++)
			cout<<elem[i]<<" ";
			cout<<endl;
	}
private:
	T elem[MAXSIZE];
};

int main()
{
	ClassB<int ,10> a;
	a.print();
	return 0;
	
}


此时MAXSIZE相当于全局变量的作用,但其为一个常整数。















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值