C++——函数模板和类模板

目录

        一、函数模板

        二、类模板


        一、函数模板

        当我们没有使用到模板的时候,我们如果要交换两个数据,那么我们就要根据交换的数据的类型,写出例如以下的函数:

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;
}

...

        虽然通过函数重载可以实现我们想要的功能,但是非常的麻烦。C++中添加了模板的使用,这就解决了这个问题。

        模板分为:函数模板类模板

        函数模板代表了一个函数家族,该函数模板与类型无关,在使用的时候才被编译器实例化,编译器会根据传入的实参类型,生成对应版本的函数

        函数模板的基本格式为:

template <typename T1,typename T2 ......>
返回值 函数名(参数列表)

        这里的typename还可以用class代替,效果是一样的。

template<class T>
void Swap(T& a, T& b)
{
	double tmp = a;
	a = b;
	b = tmp;
}

int main()
{
	int x = 1, y = 2;
	double a = 1.1, b = 2.2;

	Swap(x, y);
	Swap(a, b);
	Swap(x, b);
	return 0;
}

        这里的三次调用Swap函数前两次都是正确的,第三次则是错误的,因为这里我们定义的模板里只有一种类型,而我们传入的实参有两种类型,编译器不能识别我们到底是要用哪种类型的函数。

template<class T>
T Add(const T& a,const T& b)
{
	return a + b;
}

int main()
{
	int x = 1, y = 2;
	double a = 1.1, b = 2.2;

	Add(x, y);
	Add(a, b);
	Add(x,b);
	return 0;
}

        要解决这个问题的办法有两种,一是我们主动给对实参进行强制类型转化,但这个又会出现一个问题,类型转化后的结果是保存在一个临时变量中的,临时变量具有常性,我们形参的类型是T&,而实参是临时变量,被const修饰,所以传参的时候会发生权限的放大,还是会报错,我们要把形参也用const修饰上,才能保证形参和实参一致。

        第二种方法就是显示的实例化:在函数名后加上<>指定模板的参数类型。这样函数模板就可以支持自动的隐式类型转化了。

        同时非函数模板和函数模板可以同时存在,这个函数模板也可以实例化成这个非函数模板。当其他条件都相同时,在调用时会优先调用这个非函数模板,而不是通过函数模板去实例化。

        还有一种情况必须显示的实例化:形参中没有涉及模板类型的,比如:

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

        这种情况我们在使用这个函数的时候,模板类型和我们传入的参数无关,编译器没办法识别到我们想要实例化出什么类型,因此在调用这种函数模板时,必须显示的实例化。

        二、类模板

        类模板的用法和函数模版类似 ,但是有一点,类模板的声明和定义不建议分离到两个文件中,会出现链接错误

template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};

        当一个文件中的类模板的成员函数的声明的定义分离时,写法如下:

template<class T>
class Stack
{
public:
	Stack(int n = 4);
private:
	T* arr;
	int _size;
	int _capacity;
};


//template只作用和他相连的一个类或者函数,在类外定义的时候要重新写一遍
//这里的变量名可以于类使用的变量名不同 因为它代表的仅是一种变量类型 没有实际意义
template<class T>
Stack<T>::Stack(int n)
{
	arr = new T[n];
	_size = 0;
	_capacity = n;
}

        类模板的实例化和函数模板的实例化不同,类模板在实例化时,需要在类模板的名字后面加上<>,然后把需要实例化的类型放在<>中,类模板的名字不是真的类,实例化的结果才是一个真正的类。

template<class T>
class Stack
{
public:
	Stack(int n = 4);
private:
	T* arr;
	int _size;
	int _capacity;
};

template<class T>
Stack<T>::Stack(int n)
{
	arr = new T[n];
	_size = 0;
	_capacity = n;
}

int main()
{
	//这里的Stack<int> Stack<double>才是类型
	//Stack只是类名
	Stack<int> st1;
	Stack<double> st2;
}

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-18 16:36:04       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-18 16:36:04       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-18 16:36:04       57 阅读
  4. Python语言-面向对象

    2024-07-18 16:36:04       68 阅读

热门阅读

  1. 使用Dockerfile构建镜像

    2024-07-18 16:36:04       20 阅读
  2. python开发基础——day14 模块与包

    2024-07-18 16:36:04       23 阅读
  3. 【国内当前可用pip&conda源刷新】

    2024-07-18 16:36:04       19 阅读
  4. 解决浏览器缓存导致获取不到最新前端代码问题

    2024-07-18 16:36:04       21 阅读
  5. 6Python的Pandas:数据读取与输出

    2024-07-18 16:36:04       22 阅读
  6. linux修改时区为CST

    2024-07-18 16:36:04       17 阅读
  7. 请求通过Spring Cloud Gateway 503

    2024-07-18 16:36:04       18 阅读
  8. 使用小皮面版的Nginx服务搭建本地服务器

    2024-07-18 16:36:04       21 阅读
  9. Jenkins 安装、部署与配置

    2024-07-18 16:36:04       23 阅读
  10. Nginx:502 Bad Gateway 错误的原因及解决方法

    2024-07-18 16:36:04       18 阅读
  11. Web开发-LinuxGit基础5-本地-分支

    2024-07-18 16:36:04       20 阅读
  12. 交易-软件科技股F4(kafka、NET、snow、MongoDB)

    2024-07-18 16:36:04       20 阅读
  13. 关于Hadoop生态系统一部分的Catalog

    2024-07-18 16:36:04       24 阅读
  14. 高内聚,低耦合的解释及实例【包学包会】

    2024-07-18 16:36:04       20 阅读
  15. 网页制作技术:概念、现状与展望?

    2024-07-18 16:36:04       20 阅读
  16. Ubuntu22.04:安装Samba

    2024-07-18 16:36:04       21 阅读