栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

[C++](8)模板的初步了解

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[C++](8)模板的初步了解

文章目录
  • 泛型编程
  • 函数模板
    • 函数模板的定义
    • 函数模板的实例化
    • 模板参数的匹配原则
  • 类模板
    • 类模板的定义
    • 类模板是实例化

泛型编程

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

为了支持各种类型的两个数据的交换,我们不得不写出多个函数。比如之前写的swap函数:

void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
void Swap(double& a, double& b)
{
	double tmp = a;
	a = b;
	b = tmp;
}
void Swap(char& a, char& b)
{
	char tmp = a;
	a = b;
	b = tmp;
}

它们构成函数重载,但是代码复用率低,一旦出现新的类型,就需要用户自己添加相应的函数。代码维护性低,一但发现错误,所有函数都要一起改。

我们能否只写一个函数模板,需要什么类型的函数直接让编译器自己往里面填好了生成出来呢?

答案是可以的,我们称这种方法叫泛型编程

函数模板

模板是泛型编程的基础,要用到的关键字:template

函数模板的定义
template
返回值类型 函数名(参数列表)
{
    
}  

:typename也可以写成class,当前的角度,用这两个关键字没有区别,T是模板参数,是我们定义函数模板要用的类型名,可以自己随别取

例1:

template
void Swap(T& a, T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}

模板的声明必须带上模板参数:

//例1的声明:
template
void Swap(T& a, T& b)

模板不支持声明和定义分离到两个文件。一般是要放到一个文件中,有些地方会把文件命名成xxx.hpp,寓意头文件和定义实现内容合并在一起。

函数模板的实例化

调用Swap函数:

:传入不同类型的参数,编译器会按照模板生成不同的函数来调用。

另外,C++库里面有swap函数,我们以后也不用自己实现了


函数模板显式实例化:

如果你写得函数模板无法通过传参来推导类型,就必须手动指定:

调用时在函数模板名后面跟<>,<>内是我们自己指定的类型。

template
T* func(int c) //无法通过传参推导T的类型
{
	return newT[n];
}
int main()
{
	int* p1 = func(10);
	double* p2 = func(10);
	return 0;
}

再看下面的例子:

template
T Add(const T& a, const T& b)
{
	return a + b;
}
int main()
{
	int a = 10;
	double d = 9.8;
	Add(a, d);//此处报错:没有与参数列表匹配的 函数模板 "Add" 实例
	return 0;
}

:传入的两个参数的类型不同,T的类型无法确认,此时也可以手动指定成Add(a, d);或Add(a, d);,这样程序就能运行了,传参的时候会进行强制类型转换。

模板参数的匹配原则
int Add(int a, int b) //专门处理int类型的函数
{
	return a + b;
}

template //通用的函数模板
T Add(const T& a, const T& b)
{
	return a + b;
}

int main()
{
	int a = 1, b = 2;
	Add(a, b);
	return 0;
}

传入int类型的数据,会优先调用哪个函数呢?

通过调试发现,编译器调用的是专门处理int类型的函数,而没有去用模板实例化生成的。

如果手动指定类型Add(a, b);那么一定是调用函数模板实例化生成的。

类模板 类模板的定义
template
class 类模板名
{

};

例:

template
class Stack
{
public:
	Stack(int capacity = 0)
	{
		_a = new T[capacity];
		_capacity = capacity;
		_top = 0;
	}
	~Stack()
	{
		delete[] _a;
		_capacity = 0;
		_top = 0;
	}
	//...
private:
	T* _a;
	int _top;
	int _capacity;
};
类模板是实例化

类不像函数,函数模板可以根据传参去推导要替换的类型,而类模板没有。

类模板的实例化需要在类模板名后面跟<>,<>内的是我们自己指定的类型。

int main()
{
	Stack st1;
	Stack st2;
	return 0;
}

模板参数也支持给缺省参数,比如template,这样如果不指定类型就默认是char类型

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/993655.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号