【C++基础(十)】C++泛型编程--模板初阶

简介: 【C++基础(十)】C++泛型编程--模板初阶

1. 前言

在学习数据结构时会遇见以下的情况

数据结构中存储的类型往往不能确定

所以在实现数据结构时往往是这样做的

typedef int DateType

在写代码时用DateType来表示类型
如果想存储浮点型只需将int改为float

但是这样写会遇见一个问题:

写好数据结构类后在创建对象时

此.cpp文件只能创建一种类型的对象

对象存储的全是int/char/double类型

不能同时创建存储int的和char的对象

Data d1;//存储的int类型
Date d2;//存储的char类型

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

本章重点:

本篇文章重点讲解函数模板
和类模板的使用以及特性


2. 函数模板

请看以下函数代码:

void Swap(int& left, int& right)
{
   int temp = left;
   left = right;
   right = temp;
}
void Swap(double& left, double& right)
{
   double temp = left;
   left = right;
   right = temp;
}
void Swap(char& left, char& right)
{
   char temp = left;
   left = right;
   right = temp;
}

这样写非常的麻烦

使用模板可以使代码通用于不同类型:

swap函数模板:

template<typename T>
void Swap( T& left, T& right)
{
  T temp = left;
  left = right;
  right = temp;
}

写好上面的代码后,传int类型进去
T就会被实例化为int,以此类推

template和typename是规定
好了必须这样写,T是自己取的名字
其中,typename可以用class替换
并且一次性可以定义多个类型:

template<class T1,typename T2,class T3>

3. 函数模板原理

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


在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此

可以用下面这张图来理解:


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

第一次调用的T被推演为int类型
第二粗调用的T被推演为double

不能这样写代码:

Add(a1, d1);

系统根据a1推演出T是int类型
但是d1是double类型不能用int
类型的参数啦接受,所以会报错


  1. 显示实例化

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

int main(void)
{
 int a = 10;
 double b = 20.0;
 
 // 显式实例化
 Add<int>(a, b);
 return 0;
}

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


5. 函数模板参数的匹配规则

模板函数和普通函数可以同时存在:

// 专门处理int的加法函数
int Add(int left, int right)
{
  return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{
  return left + right;
}

在调用函数时若参数和非模板函数匹配
那么编译器会优先调用非模板函数
若非模板函数不匹配或模板函数更匹配
那么编译器会优先调用模板函数

Add(10,20)//调用非模板
Add(11.1,6.3);//调用模板

6. 类模板

类模板的应用非常广泛

像开头提到的数据结构问题

类模板的定义格式:

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

和函数模板类似,类模板也可以同时

定义多个模板参数

写一个简易的顺序表:

template<class T>
class Vector
{ 
public :
 Vector(size_t capacity = 10)
 : _Data(new T[capacity])
 , _size(0)
 , _capacity(capacity)
 {}
 T& operator[](size_t pos)
 {
   assert(pos < _size);
   return _Data[pos];
 }
 
private:
 T* _Data;
 size_t _size;
 size_t _capacity;
};

所有实际类型需要出现的地方用T代替


7. 类模板的实例化

和函数模板不同,类模板没有隐式推演
用户必须显示实例化

Vector<int> v1;

注意:
Vector是类名
Vector< int >才是类型

当在类中声明一个函数
但是想在类外定义时
若函数的参数或内部使用的类型
和模板有关系,那么必须这样写:

template<class T>
class Vector
{ 
public :
    //类中声明函数
  void push_back(T x);
private:
 T* _Data;
 size_t _size;
 size_t _capacity;
};

类外定义:

template<class T>
void Vector<T>::push_back(T x)
{
  _Date[_size] = x;
  _size++;
}

注:必须要再加上类模板template

并且要指定类域


8. 总结以及拓展

泛型编程是C++的一大利器

它极大的减少了代码的复杂程度

并且增加了代码的可读性

C++基础部分的内容已经全部结束
下一阶段进入C++中阶:STL的使用

拓展:

泛型编程拓展阅读


🔎 下期预告:STL库的介绍以及使用 🔍


相关文章
|
2月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
106 10
|
2月前
|
存储 C++ UED
【实战指南】4步实现C++插件化编程,轻松实现功能定制与扩展
本文介绍了如何通过四步实现C++插件化编程,实现功能定制与扩展。主要内容包括引言、概述、需求分析、设计方案、详细设计、验证和总结。通过动态加载功能模块,实现软件的高度灵活性和可扩展性,支持快速定制和市场变化响应。具体步骤涉及配置文件构建、模块编译、动态库入口实现和主程序加载。验证部分展示了模块加载成功的日志和配置信息。总结中强调了插件化编程的优势及其在多个方面的应用。
280 63
|
2月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
53 2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
|
2月前
|
安全 程序员 编译器
【实战经验】17个C++编程常见错误及其解决方案
想必不少程序员都有类似的经历:辛苦敲完项目代码,内心满是对作品品质的自信,然而当静态扫描工具登场时,却揭示出诸多隐藏的警告问题。为了让自己的编程之路更加顺畅,也为了持续精进技艺,我想借此机会汇总分享那些常被我们无意间忽视却又导致警告的编程小细节,以此作为对未来的自我警示和提升。
161 6
|
2月前
|
编译器 程序员 C++
【C++打怪之路Lv7】-- 模板初阶
【C++打怪之路Lv7】-- 模板初阶
18 1
|
2月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
86 11
|
2月前
|
存储 C++ 容器
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器1
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
55 5
|
2月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
47 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
2月前
|
算法 编译器 C++
【C++篇】领略模板编程的进阶之美:参数巧思与编译的智慧
【C++篇】领略模板编程的进阶之美:参数巧思与编译的智慧
83 2
|
7天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
21 2