【C++从入门到放弃】模板介绍(函数模板、类模板)

这篇具有很好参考价值的文章主要介绍了【C++从入门到放弃】模板介绍(函数模板、类模板)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🧑‍💻作者: @情话0.0
📝专栏:《C++从入门到放弃》
👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢!

【C++从入门到放弃】模板介绍(函数模板、类模板)


一、泛型编程是什么?

  以我们之前所学的知识,假如要实现一个通用的加法函数,那么可以通过函数重载的方式来实现。

void Add(const int& a,const int& b)
{
	return a+b;
}
void Add(const double& a,const double& b)
{
	return a+b;
}
void Add(const char& a,const char& b)
{
	return a+b;
}

使用函数重载虽然可以实现,但是有以下几个不好的地方:

  1. 重载的函数仅仅只是参数类型不同,代码的复用率比较低,一旦有新类型的参数出现时,就需要增加对应的函数;
  2. 代码的可维护性比较低,一个出错可能所有的重载均出错。

  为了解决上面因为函数重载而出现的几个问题,便有了泛型编程,那什么是泛型编程呢?

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础,而这个模板就类似于一个浇筑模具,通过给这个模具中填充不同的材料(参数类型)来获得不同材质的铸件(生成的具体类型代码)。

  1. 模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型;
  2. 模板是一种对类型进行参数化的工具;
  3. 通常有两种形式:函数模板和类模板;
  4. 函数模板仅针对参数类型不同的函数;
  5. 类模板仅针对数据成员和成员函数类型不同的类;
  6. 使用模板的目的就是能够让程序员编写与类型无关的代码。比如编写了一个求和两个整型int 类型的Add函数,这个函数就只能实现int 型,对double,字符这些类型无法实现,要实现这些类型的交换就要重新编写另一个Add函数。使用模板的目的就是要让这程序的实现与类型无关,比如一个Add模板函数,即可以实现int 型,又可以实现double型的求和

二、函数模板

1. 什么是函数模板?

  函数模板代表了一个函数聚合体,该函数模板与参数类型无关,在函数调用的时候根据传参的类型将函数模板里的参数进行参数化,也就是根据实参类型产生函数的特定类型版本。

2. 函数模板的格式

template<typename T1, typename T2,,typename Tn>
返回值类型 函数名(参数列表){}

示例:

template <typename T>    //   模板参数列表:声明类型
	
T Add(const T& a,const T& b)
{
	return a+b;
}

注意:typename是用来定义模板参数关键字,也可以使用class,但是不能使用struct代替class

3. 函数模板的原理

  函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。

  在这里,我举一个例子,我们上面所列举的这个函数模板就是相当于一个制作螺丝的模具,它本身不是螺丝,需要用这个模具在压铸出来螺丝,这个螺丝才相当于真正的函数,使用螺丝也就相当于调用函数。

  在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。

4. 函数模板实例化

  用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。

4.1 隐式实例化

  让编译器根据实参推演模板参数的实际类型

template<class T> 
T Add(const T& left, const T& right) 
{
 	return left + right; 
}
int main()
{
	int a1 = 10, a2 = 20;
 	double d1 = 10.0, d2 = 20.0;
 	Add(a1, a2);
 	Add(d1, d2);
 	Add(a1,d2); //错误
 	Add(a1,(int)d1);
 	return 0;
 }

  解释一下为什么第三条 Add 语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演出其实参类型,通过实参 a1 将 T 推演为 int,通过实参 d1 将 T 推演为 double 类型,但模板参数列表中只有一个 T,编译器无法确定此处到底该将 T 确定为 int 或者 double 类型而报错。注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,那就是编译器的锅。
  而对于上述的问题可以有两种处理方式:用户自己强制转化(第四条Add语句);使用显示实例化

4.2 显式实例化

  在函数名后的<>中指定模板参数的的实际类型

int main() 
{
 	int a = 10;
 	double b = 10.0; 
 	double c = 20.0;
 	Add<int>(a, b);
 	Add<int>(b, c);
 	return 0; 
}

如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

5. 模板参数匹配原则

  1. 一个非模板函数和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
// 专门处理int的加法函数
int Add(int left, int right)
{
	return left + right;
}
 
// 通用加法函数
template<class T>
T Add(T left, T right)
{
	return left + right;
}
 
void Test()
{
	Add(1, 2); // 与非模板函数匹配,编译器不需要特化
	Add<int>(1, 2); // 调用编译器特化的Add版本
	Add(1,2.0); //调用非模板函数,但是可能会导致数据丢失
}
  1. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数(不需要参数类型的转换), 那么将选择模板。
// 专门处理int的加法函数
int Add(int left, int right)
{
	return left + right;
}
 
// 通用加法函数
template<class T1,class T2>
T Add(T1 left, T2 right)
{
	return left + right;
}
 
void Test()
{
	Add(1, 2); // 与非模板函数匹配,编译器不需要特化
	Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
}
  1. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

二、类模板

3.1 类模板的定义格式

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

// 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具

template<class T>

class Vector

{ 

public :
 Vector(size_t capacity = 10)
 : _pData(new T[capacity])
 , _size(0)
 , _capacity(capacity)
 {}
 
 // 使用析构函数演示:在类中声明,在类外定义。

 ~Vector();
 
 void PushBack(const T& data)void PopBack()// ...

 
 size_t Size() {return _size;}
 
 T& operator[](size_t pos)
 {
 assert(pos < _size);
 return _pData[pos];
 }
 

private:
 T* _pData;
 size_t _size;
 size_t _capacity;
};
 

// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表

template <class T>

Vector<T>::~Vector()
{
 if(_pData)
 delete[] _pData;
 _size = _capacity = 0;
}

3.2 类模板实例化

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

// Vector类名,Vector<int>才是类型

Vector<int> s1;
Vector<double> s2;

总结

以上就是我自己对于学习模板的总结,希望各位看官遇到不足之处帮我指正出来,咱们一块互相学习,讨论,也希望我的略解能够帮助到你。
【C++从入门到放弃】模板介绍(函数模板、类模板)文章来源地址https://www.toymoban.com/news/detail-413502.html

到了这里,关于【C++从入门到放弃】模板介绍(函数模板、类模板)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++入门到放弃(01)——引用 #include

    C++中包含头文件存在两种不同的形式,尖括号和双引号\\\"\\\",其区别在于搜索范围和搜索顺序。 以Visual Studio 2022为例,我们创建一个工程,在里面添加主函数main.cpp的文件,以及头文件test.h Project ├── main.cpp └── test.h 只可以访问 系统目录下的头文件(.h),\\\"\\\"可以访问 当前文

    2024年02月16日
    浏览(37)
  • c++从入门到放弃,小白踩坑记录1

    错误问题描述 没有与这些操作数匹配的运算符操作数类型为std::basic_ostream char,std::char traits char unknown-type 错误代码 错误原因 代码的“end”为错误写发,应该是“endl” 修改后的正确代码

    2024年02月06日
    浏览(45)
  • 【C++从入门到放弃】vector深度剖析及模拟实现

    🧑‍💻作者: @情话0.0 📝专栏:《C++从入门到放弃》 👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢! vector 是表示 可变大小数组 的序列容器。 就像数组一样,vector也采用的 连续存储空间 来存储元素。也就是意味着可以

    2024年02月07日
    浏览(47)
  • 【C++从入门到放弃】list深度剖析及模拟实现

    🧑‍💻作者: @情话0.0 📝专栏:《C++从入门到放弃》 👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢! list 是允许在序列内的任何位置进行 常量时间的插入和删除 操作的序列容器,并且该容器可以前后双向迭代。 list 的底

    2024年02月10日
    浏览(46)
  • C++入门之stl六大组件--String库函数的介绍

    文章目录 一、为什么学习string类 1.C语言中的字符串 二、标准库中的string类 1.string类 2.string类的常用接口 1.string类对象的常见构造 2.string类对象的容量操作 3.string类对象的访问以及遍历操作 4.string类对象的修改操作 5.string类的非成员函数 总结   C语言中,字符串是以\\0结尾的

    2024年02月16日
    浏览(44)
  • 【C++从入门到放弃】string全方面分析(常用接口、模拟实现)

    🧑‍💻作者: @情话0.0 📝专栏:《C++从入门到放弃》 👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢! 在学习C++的过程中,必定有一个非常重要的工具就是STL(标准模板库):C++标准库的重要组成部分,它不仅是一个可复

    2024年02月02日
    浏览(47)
  • 深聊性能测试,从入门到放弃之: Windows系统性能监控(三)任务管理器介绍及使用。

    关于Windows系统性能监控的前两篇 《 Windows系统性能监控(一) 性能监视器介绍及使用 》 《 Windows系统性能监控(二) 资源监控器介绍及使用 》 私下里有很多同学反馈,说学到了很多, 其实,在平时,如果我们能把集成好的服务监控应用起来, 你会收到意想不到的惊喜, 毕竟,

    2024年02月03日
    浏览(40)
  • 深聊性能测试,从入门到放弃之: Windows系统性能监控(二) 资源监控器介绍及使用。

    小屌丝 :鱼哥,我看了你这篇《Windows系统性能监控(一) 性能监视器介绍及使用》,让我学到了好多知识。 小鱼 :嗯,我自己在写这篇文章的时候,也学到了好多。 小屌丝 :是吗,你不都是知道了,咋还又学到了好多; 小鱼 :这个很正常啊,你把你会的知识,重新以文字

    2024年01月25日
    浏览(49)
  • 【C++】——模板(泛型编程+函数模板+类模板)

    之前我们学习了函数重载,让我们在写相似函数的时候非常方便,但函数重载还有很多不足的地方,比如,每次写相似函数的时候,都要我们重新重载一个逻辑、代码几乎一样的函数,这就导致了我们的效率变低,所以我们今天来学习C++模板的相关知识点,学习完模板之后,

    2024年02月05日
    浏览(46)
  • 浅述C++模板——函数模板及类模板

    模板作为 C++ 的一大特色,对于泛型编程有着重要的作用。同时,对于大规模类似的函数或是类型不确定的类,模板都起了至关重要的作用。 在开始学习模板之前,我们首先需要了解模板。先看下面一个例子: 我们可以轻易发现,对于函数 func_one、func_two,两者实现的功能基

    2024年02月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包