C++:模板

时间:2024-10-28 16:32:45

目录​​​​​​​

一.泛型编程

二.模板

函数模板

类模板


一.泛型编程

在C++中,支持函数重载,如果我们通过函数重载实现通用的交换函数,写法如下:

void Swap(int& left, int& right)
{
 int temp = left;
 left = right;
 right = temp;
}
void Swap(double& left, double& right)
{
 double temp = left;
 left = right;
 right = temp;
}
void Swap(char& left, char& right)
{
 char temp = left;
 left = right;
 right = temp;
}
......

非常冗余,于是我们引入泛型编程的概念:通过编写与类型无关的代码,实现代码的复用。而在C++中,模板就是泛型编程的基础。

二.模板

模板有两种:函数模板和类模板

函数模板

语法:

template<typename T1, typename T2, ..., typename T3>

返回值类型 函数名(参数列表){}

typename是用来定义函数模板的关键字,也可以使用class关键字。

样例:

//交换函数模板
template<typename T>
void Swap(const T& x, const T& y)
{
	T tmp = x;
	x = y;
	y = tmp;
}

int main()
{
	int i1 = 1, i2 = 2;
	double d1 = 1.1, d2 = 2.2;
	char c1 = 'a', c2 = 'b';

    //隐式实例化
	Swap(i1, i2);//隐式(推导)生成void Swap(const int& x, const int& y);
	Swap(d1, d2);//隐式(推导)生成void Swap(const double& x, const double& y);
	Swap(c1, c2);//隐式(推导)生成void Swap(const char& x, const char& y);

    //显式实例化
    float f1 = 1.1, f2 = 2.2;
    Swap<float>(f1, f2);//显式(手动)生成void Swap(const float& x, const float& y);
	return 0;
}

模板函数是一个蓝图,非具体函数,而是编译过程中,编译器根据蓝图生成了具体类型的函数。

模板参数实例化的两种方式:

隐式实例化:编译器根据实参推演模板参数的实际类型

显式实例化:函数名<>,在<>中指定模板参数的实际类型

 如果一个非模板函数和同名函数模板同时存在,且调用时实参和非模板函数完全匹配,编译器会优先调用这个非模板函数。

类模板

语法:

template<typename T1, typename T2, ... , typename Tn>

class 类模板名

{

        //成员定义

};

实现一个栈的类模板:

//Stack
template<typename T>
class Stack
{
public:
	//构造函数
	Stack(int n = 4)
		:_arr(new T[n])
		,_top(0)
		,_capacity(n)
	{}

	//析构函数
	~Stack()
	{
		delete[] _arr;
		_arr = nullptr;
		_top = _capacity = 0;
	}

	void Push(const T& x)
	{
		T* tmp = new T[_capacity * 2];
		memcpy(tmp, _arr, sizeof(T) * _top);

		delete[] _arr;
		_arr = tmp;
		_capacity *= 2;

		_arr[_top++] = x;
	}

	void Pop()
	{
		_top--;
	}

	//...
private:
	T* _arr;
	int _top;
	int _capacity;
};

int main()
{
    //Stack<int>和Stack<double>是类型,Stack仅仅是类名
	Stack<int> st_i;//存储int类型数据的栈
	Stack<double> st_d;//存储double类型数据的栈
	return 0;
}

 上述代码中,Stack<int>和Stack<double>是显式实例化出的两个存储不同数据类型的栈,它们属于不同的类型。

类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

今天的内容就到这,感谢大家的支持!