C++ 模板

在本文中,您将学习C ++中的模板。您将学习如何使用模板的功能进行通用编程。

模板是C ++的强大功能,可让您编写通用程序。简而言之,您可以使用模板创建一个函数或一个类来处理不同的数据类型。

模板通常在较大的代码库中使用,目的是实现代码的可重用性和程序的灵活性。

模板的概念可以两种不同的方式使用:

  • 函数模板

  • 类模板

函数模板

函数模板的工作方式与普通函数相似,只是有一个不同之处。

单个函数模板可以一次处理不同的数据类型,但是单个普通函数只能处理一组数据类型。

通常,如果需要对两种或更多种类型的数据执行相同的操作,则可以使用函数重载来创建具有所需函数声明的两个函数。

但是,更好的方法是使用函数模板,因为您可以使用较少的代码来执行相同的任务。

如何声明函数模板?

函数模板以关键字template开头,其后是<>内的模板参数,然后是函数声明。

template <class T>
T someFunction(T arg)
{
   ... .. ...
}

在上面的代码中,T是一个模板参数,它接受不同的数据类型(如int,float等),而class是关键字。

在上面的示例中,您还可以使用关键字typename代替class。

当将数据类型的参数传递给someFunction()时,编译器会为给定数据类型生成someFunction()的新版本。

示例1:查找最大数量的函数模板

程序使用函数模板显示两个数字中最大的一个。

//如果将两个字符传递给函数模板,则显示ASCII值较大的字符。

#include <iostream>
using namespace std;

// template function
template <class T>
T Large(T n1, T n2)
{
	return (n1 > n2) ? n1 : n2;
}

int main()
{
	int i1, i2;
	float f1, f2;
	char c1, c2;

	cout << "输入两个整数:\n";
	cin >> i1 >> i2;
	cout << Large(i1, i2) <<" 更大。" << endl;

	cout << "\n输入两个浮点数:\n";
	cin >> f1 >> f2;
	cout << Large(f1, f2) <<" 更大。" << endl;

	cout << "\n输入两个字符:\n";
	cin >> c1 >> c2;
	cout << Large(c1, c2) << " 具有较大的ASCII值。";

	return 0;
}

输出结果

输入两个整数:
5
10
10 is larger.

输入两个浮点数:
12.4
10.2
12.4 is larger.

输入两个字符:
z
Z
z 具有较大的ASCII值。

在上面的程序中,定义了一个函数模板Large(),它接受数据类型为T的两个参数n1和n2。T表示这个参数可以是任何数据类型。

Large()函数使用简单的条件操作返回两个参数中最大的一个。

在main()函数内部,声明了三种不同数据类型的变量:int,float和char。 然后将变量作为普通函数传递给Large()函数模板。

在运行时,将整数传递给模板函数时,编译器知道必须生成一个Large()函数来接受int参数,并且也是这样做的。

同样,当传递浮点数据和char数据时,它知道自变量数据类型并相应地生成Large()函数。

这样,仅使用一个函数模板即可替换三个相同的常规函数,并使您的代码更少也更容易维护。

示例2:使用函数模板交换数据

程序使用函数模板交换数据。

#include <iostream>
using namespace std;

template <typename T>
void Swap(T &n1, T &n2)
{
	T temp;
	temp = n1;
	n1 = n2;
	n2 = temp;
}

int main()
{
	int i1 = 1, i2 = 2;
	float f1 = 1.1, f2 = 2.2;
	char c1 = 'a', c2 = 'b';

	cout << "在将数据传递给函数模板之前。\n";
	cout << "i1 = " << i1 << "\ni2 = " << i2;
	cout << "\nf1 = " << f1 << "\nf2 = " << f2;
	cout << "\nc1 = " << c1 << "\nc2 = " << c2;

	Swap(i1, i2);
	Swap(f1, f2);
	Swap(c1, c2);

        cout << "\n\n将数据传递给函数模板后。\n";
	cout << "i1 = " << i1 << "\ni2 = " << i2;
	cout << "\nf1 = " << f1 << "\nf2 = " << f2;
	cout << "\nc1 = " << c1 << "\nc2 = " << c2;

	return 0;
}

输出结果

在将数据传递给函数模板之前。
i1 = 1
i2 = 2
f1 = 1.1
f2 = 2.2
c1 = a
c2 = b

将数据传递给函数模板后。
i1 = 2
i2 = 1
f1 = 2.2
f2 = 1.1
c1 = b
c2 = a

在此程序中,不是通过传递值来调用函数,而是通过引用进行调用。

Swap()函数模板接受两个参数,并通过引用交换它们。

类模板

与函数模板一样,您也可以为通用类操作创建类模板。

有时,您需要一个适用于所有类的类实现,只是所使用的数据类型不同。

通常,您需要为每种数据类型创建一个不同的类,或者在一个类中创建不同的成员变量和函数。

这将会增加很类似的代码,并且将难以维护。

但是,类模板使对所有数据类型重复使用相同的代码变得更容易。

如何声明一个类模板?

template <class T>
class className
{
   ... .. ...
public:
   T var;
   T someOperation(T arg);
   ... .. ...
};

在上面的声明中,T是模板参数,它是所使用数据类型的占位符。

在类内部,成员变量var和成员函数someOperation()均为T类型。

如何创建类模板对象?

要创建类模板对象,需要在创建时在< >中定义数据类型。

className<dataType> classObject;

例如:

className<int> classObject;
className<float> classObject;
className<string> classObject;

示例3:使用类模板的简单计算器

程序使用类模板对两个数字进行加,减,乘和除运算

#include <iostream>
using namespace std;

template <class T>
class Calculator
{
private:
	T num1, num2;
	
public:
	Calculator(T n1, T n2)
	{
		num1 = n1;
		num2 = n2;
	}
	
	void displayResult()
	{
		cout << "Numbers are: " << num1 << " and " << num2 << "." << endl;
		cout << "Addition is: " << add() << endl;
		cout << "Subtraction is: " << subtract() << endl;
		cout << "Product is: " << multiply() << endl;
		cout << "Division is: " << divide() << endl;
	}
	
	T add() { return num1 + num2; }
	
	T subtract() { return num1 - num2; }
	
	T multiply() { return num1 * num2; }
	
	T divide() { return num1 / num2; }
};

int main()
{
	Calculator<int> intCalc(2, 1);
	Calculator<float> floatCalc(2.4, 1.2);
	
	cout << "Int results:" << endl;
	intCalc.displayResult();
	
	cout << endl << "Float results:" << endl;
	floatCalc.displayResult();
	
	return 0;
}

输出结果

Int results:
Numbers are: 2 and 1.
Addition is: 3
Subtraction is: 1
Product is: 2
Division is: 2

Float results:
Numbers are: 2.4 and 1.2.
Addition is: 3.6
Subtraction is: 1.2
Product is: 2.88
Division is: 2

在上面的程序中,声明了一个类模板Calculator。

该类包含两个类型为T的私有成员:num1和num2,以及用于初始化成员的构造函数。

它还包含公共成员函数,用于计算数字的加,减,乘和除,以返回用户定义的数据类型的值。 同样,函数displayResult()将最终结果输出显示到屏幕上。

在main()函数中,分别为数据类型创建了两个不同的Calculator对象intCalc和floatCalc:int和float。 使用构造函数初始化值。

注意,我们在创建对象时使用<int>和<float>。这些告诉编译器用于类创建的数据类型。

这将为int和float分别创建一个类定义,然后相应地使用它们。

然后,displayResult()两个对象都被调用,

然后,调用这两个对象的displayResult(),它执行计算器操作并显示输出。