C++基础总结系列之【模板】

目录

 

模板

what

why

how


本文仅对模板的一些概念及基本用法做总结供初学者参考及复习,大神勿喷......

模板

what

对于重载机制而言,C++能够通过函数的不同参数以及所属类不同正确调用重载函数。

但当面对重载函数只有参数类型不同,其他代码都相同时,需要一种机制增强它的复用性,使得变量类型也参数化,因而引入模板。

可以理解为定义一个公共的需求,比如word文档的模板,定义了大家都有可能用到的样式,C++的模板也就是定义一个公共的模块,把一些类似的功能的模块归类为一个模板,

扫描二维码关注公众号,回复: 13123017 查看本文章

why

当遇到代码相同,参数变量类型不同的场景时,为了增强代码的复用和扩展性,减少了代码的冗余。

how

基本语法:

  • 函数模板

Template <class或者也可以用typename T>

返回类型 函数名(形参表)
{//函数定义体 }

  • 类模板

template < class或者也可以用typename T >
class类名{
//类定义......
};

使用注意:

  1. 模板传入的具体类型在编译时无法确定,在调用时才确定其类型;
  2. 编译器从函数模板通过具体类型产生不同的函数;编译器会对函数模板进行两次编译:在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译,具体参考:https://blog.csdn.net/qq_39108291/article/details/102019805?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control
  3. 其作用域仅限模板声明下方的函数或类,在模板声明与函数或类之间尽可能不要加代码;
  4. 对于模板类,只要定义类时用到了模板,下面调用的时候一定要用<>,传入具体类型,如果不确定具体类型,再套入一个模板类型。

附一段可以指定规则排序任意类型数组的简单冒泡排序及测试代码:

#include <iostream>
using namespace std;

bool Rule(int a,int b)
{
	return a%3;
}

bool Rule1(int a,int b)
{
	return a<b;
}
template <typename T>
void BubbleSort(T* arr,int n,bool (*pfn)(T,T))
{
	for(int i = 0; i < n-1; i++)
	{
		for(int j = 0; j < n-1-i; j++)
		{
			if((*pfn)(arr[j],arr[j+1]))
			{
				T temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}
		}
	}
}

int main()
{
	int arr[] = {3,8,0,4,1,2,5,9,7,6};
	BubbleSort(arr,sizeof(arr)/sizeof(arr[0]),&Rule);
	for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
		cout<<arr[i]<<" ";
	cout<<endl;

	BubbleSort(arr,sizeof(arr)/sizeof(arr[0]),&Rule1);
	for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
		cout<<arr[i]<<" ";
	cout<<endl;
	system("pause");
	return 0;
}

运行结果:

封装的简单的模板链表类代码如下(使用尾插法、头删除):

#include <iostream>
using namespace std;

template <typename T>
class CList
{
private:
	struct Node{
		T val;
		Node* pNext;
	};
	Node* m_pHead;		//头指针
	Node* m_pTail;		//尾指针
	int m_nLength;		//链表长

public:
	CList()
	{
		m_pHead = nullptr;
		m_pTail = nullptr;
		m_nLength = 0;
	}
	//CList(int count,T val = 0)		//通过构造函数构造一个链表
	//{
	//	m_pHead = nullptr;
	//	m_pTail = nullptr;
	//	m_nLength = 0;

	//	for(int i = 0; i < count; i++)
	//		Push_Back(val);
	//}
	~CList()
	{
		while(m_pHead)
			Pop_Front();
	}
public:
	void Push_Back(T val)
	{
		//初始化一个节点
		Node* node = new Node;
		node->val = val;
		node->pNext = nullptr;

		//插入到链表尾部
		if(!m_pHead)
		{
			m_pHead = node;
			m_pTail = node;
		}
		else
		{
			m_pTail->pNext = node;
			m_pTail = node;
		}
		
		m_nLength++;
	}
	void Pop_Front()
	{
		//链表中没有节点
		if(!m_pHead)
			return;
		//有一个节点
		if(m_pHead == m_pTail)
		{
			delete m_pHead;
			m_pHead = nullptr;
			m_pTail = nullptr;
			m_nLength = 0;
			return ;
		}
		//有多个节点
		Node* pDel = m_pHead;
		m_pHead = m_pHead->pNext;
		delete pDel;
		pDel = nullptr;
		m_nLength--;
	}
	void Traverse()
	{
		Node* pTemp = m_pHead;
		while(pTemp)
		{
			cout<<pTemp->val<<" ";
			pTemp = pTemp->pNext;
		}
		cout<<"链表长度为"<<m_nLength<<endl;
	}
};

int main()
{
	CList<int> list;
	for(int i = 0; i < 10; i++)
		list.Push_Back(i);
	list.Pop_Front();
	list.Traverse();

	CList<double> list_d;
	list_d.Push_Back(1.1);
	list_d.Push_Back(1.2);
	list_d.Push_Back(1.3);
	list_d.Traverse();

	CList<char> list_c;
	list_c.Push_Back('a');
	list_c.Push_Back('b');
	list_c.Traverse();

	system("pause");
	return 0;
}

运行结果:

猜你喜欢

转载自blog.csdn.net/qq_37348221/article/details/113270443