C++模板(函数模板、类模板)


绪论

思想决定行动,行动养成习惯,习惯形成品质,品质决定命运。——陶行知

本章讲的是c++的初阶模板,全文不算代码字数少的可怜,但模板是我们c++必须学的一个宝物,他的出现可是c++的飞跃性成就!下面将主要以代码的方式来进行语法学习。

话不多说安全带系好,发车啦(建议电脑观看)


附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要


思维导图:

要XMind思维导图的话可以私信哈


目录

1.泛型编程

2.函数模板

2.1实现模板的原理

2.2函数模板的实例化

3.类模板


1.泛型编程

知识点:

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段模板是泛型编程的基础有点抽象。

他们在一些重复性很强的代码上虽然使用函数重载可以实现,但是终究有不好的地方,重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数,代码的可维护性比较低,一个出错可能所有的重载均出错。
具体那下面的代码具体展示:
下面是swap交换函数,此时就是对不同的类型就需要不同的交换函数:

void swap(int& x, int& y)
{
    int tmp = x;
    x = y;
    y = tmp;
}

void swap(char& x, char& y)
{
    char tmp = x;
    x = y;
    y = tmp;
}

void swap(float& x, float& y)
{
    float tmp = x;
    x = y;
    y = tmp;
}

// ......

对此c++,为了解决这个问题就提出了一个新语法:模板(模板就像一个模具一样我们创造出来的东西形状都一样,只是我们放进去的材料不同最终出来的也东西就有所不同。在上面的交换函数中,交换的方法是一样的,只是他们的类型不同,也就是所谓的换汤不换药还是老一套,所以就能用模板来快速的实现相类函数的创建)。


2.函数模板

知识点:

函数模板概念:函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
模板的语法:

template<typename T1, typename T2 ...> 、 template<class T, ....>  

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

{}

  • 其中class 和 typename是一样的效果我们都可以使用

  • 模板需要和需要模板的函数紧挨着一起出现。模板参数的使用范围就是在其下方的函数/类的域中。

 使用练习(注意看注释):

//template<class Ty>和下面的是效果一样的,并且内部的Ty是和变量名一样可以自行diy的
template<typename T>
void Swap(T& x, T& y) {
	T tmp = x;
	x = y;
	y = tmp;
}


// 我们可以定义多个模板参数,来分开识别使用,防止出现两个参数的类型不同的情况
template<class T1,typename T2>
void Func(T1& x, T2& y)//此处定义了两个模板参数,就能对应对当两个类型不同的情况
{
	cout << x << ' ' << y << endl;
}

int main()
{
	int a = 0 , b = 1;
	double c = 1.1, d = 2.2;
	Swap(a, b);
	Swap(c, d);


	int e = 10;
	double f = 10.4;
	Func(e, f);

	return 0;
}


细节:

2.1实现模板的原理

模板的实现原理其就和现实中的很像,通过一个模具,重复多次某种类似的过程而模具就像上面代码中的模板下面的函数一样,在这过程中通过这个模具会创建出多个看不见的重载的函数,其实本质还是创建了多个函数并且去调用了这些函数,只是这实现过程被编译器代替了而已(模板的实例化)。

注意:虽然他们用的是同一个模板,但是他们调用的函数时不一样的!

附:其实在c++库中已经为我们写好了这个交换函数,所以说从后面开始我们不需要在自己去实现swap函数,直接用就可以 , swap(变量,变量);


2.2函数模板的实例化

  • 用不同类型的参数使用函数模板时,称为函数模板的实例化。
  • 模板参数实例化分为:隐式实例化和显式实例化
  1. 隐式实例化:给参数去直接直接识别类型,然后给到模板参数创建函数,就如上面的练习一样。
  2. 显示实例化:自己直接给函数的模板参数在调用前确定类型

举例练习:

显示实例化的写法:

在函数和参数之间加上方括号 , 并且在内部加上类型  如 :Func<int>(a,b)。

具体如下:

template<typename T>
T* Alloc(int n)
{
	return new T[n];
}

int main()
{
	int* ptr = Alloc<int>(10);//此时的<int>就是一个显示的实例化,直接给这个函数的模板参数定义了类型int
	return 0;
}

3.类模板

知识点:

  • 类模板的定义格式:类模板和函数模板使用方法和功能都几乎一样,只是用处有些许的不同(具体将通过代码展示)
  • 对于函数模板来说他的作用域是挨着的函数局部域,而对于类模板来是作用于紧挨着的整个类域里面。

细节:

如果加上了类模板的话,就会改变其类的类型: 

类型: 类名<所有模板参数> 

类的类名还是一样  

练习使用(再次理解,注意注释)

template<typename T>
class Stack
{
public:
	Stack(int capacity = 4)
	{
		_arr = new T[capacity];
		int _size = 0;
		int _capacity = capacity;
	}

	void Push(const T& x);


	~Stack()
	{
		delete _arr;
		_size = 0;
		_capacity = 0;
	}

private:
	T* _arr;
	int _size;
	int _capacity;
};

template<typename T>
void Stack<T>::Push(const T& x)//此时我们定义全局函数时,需要我们指定类域才能使用其内部的成员
//而对于函数模板来说,此时的类型也该变成 Stack<模板参数>
{
	//CheckCapacity()
	_arr[_size] = x;
	_size++;
}

int main()
{
	Stack<int> st1;//显示实例化,此处必须加上这个显示...
	Stack<double> st2;//double

	//这样写我们就不用像cyy那样需要去改变 TypeDate 了
	//并且,可以同时使用多种类型的栈
    //C语言不能同时拥有,因为C语言的TypeDate只能在一处使用,就导致定死后不能用于
	//另外一处新的类型的对象中,而模板就能突破这个界限,创建多个类型不同功能一样的函数
	return 0;
}

本章完。预知后事如何,暂听下回分解。

如果有任何问题欢迎讨论哈!

如果觉得这篇文章对你有所帮助的话点点赞吧!

持续更新大量C++细致内容,早关注不迷路。

猜你喜欢

转载自blog.csdn.net/ZYK069/article/details/130865195