【C++语言】模板(内附精美思维导图)

简介: 【C++语言】模板(内附精美思维导图)

思维导图附上

看不清楚戳这里【模板思维导图】

链接部分思维导图是备注展开的,图片是没展开的。


1.为什么要有模板?

其实用现实生活中的话都可以回答,比如冰棍模具,我们可以根据这个模具的样子,加入不同的调料,得到形状造型相同,但内部调料类型不同,的不同冰棍。这也是我们C++模板,具体到一类容器来说,容器相同,但内部类型不同。都用同一个类模板创造的。


总结就是:告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码


2.模板的原理

我们对模板的使用,并不是直接使用模板,而是我们提供类型,而编译器会根据模板,生成一份对应我们提供类型的实例化类,我们也就可以调用它来创建类对象了。注意:提供不同类型,会生成不同实例化类。


此图把原理分析的很清楚了:

851bfbf3ae094a6d90ba8c7ddd7a09b7.png

3.模板的参数

1)类型模板参数

类型模板参数就是class/typename 加上类型组成的范式类型列表。

class:

template<class T1, class T2,......,class Tn>


typename:

template<typename T1, typename T2,......,typename Tn>

两者在此处并没有很大的区别,typename比class多一个“哄骗”声明。就是在编译阶段告诉编译器,我后面的是一个类型,你让它过,等它实例化以后你自己去找。编译器就说好让它通过了。但到了后续不一定能成功运行。因为编译器去找了,但不一定是一个类型,有可能是一个类静态成员变量。甚至还有可能不存在这个东西。只有实例化后才能知道。

//typename就和int那些声明一样,但是int那些声明是确定的,typename的声明是不一定有保障的
int a;    //a一定是int
typename T::iterator it; //告诉编译器这个iterator这是T(范式)类型中的类型,你等它实例化后自己去找
//与作用限定符 类::内部类/typedef别名/静态成员变量

2)非类型模板参数

非类型模板参数是指,除了class/typename+类型名称,还可以整形家族+变量名称都可以给缺省

比如:array 静态数组

template<class T,size_t N=1000>;
class array{

private:
    T _array[N];
    int  _size;
};


4.模板的分类

注意:模板的作用域就是该函数模板或者类模板

1)函数模板

函数模板定义:

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


函数模板实例化:

//以Add函数为例:
template<class T>
T Add(T left, T right)
{
  return left + right;
}

Add(1, 2); //调用实例化
Add<int>(1,2);//显示实例化,告诉编译器我是什么类型,可以对我的数据进行强转

2)类模板

类模板的定义:

emplate <class T1,class T2,...,class Tn>
class 类模板名
{
  //类内的成员函数和成员变量
}

类模板的实例化:

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

// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;


5.模板的特化

我们不论在用函数模板还是类模板的时候,都有一些情况下需要调整:

比如:我们想要比较两个指针所指向的整形对象的大小,我们把int*传到函数模板,x,y是指针,但它没有解引用操作,只是直接比较地址。所以得到的结果不符合我们的需求,或者我们想针对部分类型执行其他代码(有一定代码限制的作用),需要更改,这里就可以用到我们的模板的特化。

template<class T>
bool Less(T x,T y)
{
  return x < y;
}

1)函数模板特化:

接着上面的例子,我们可以做以下特化操作:

//全特化,很具体
template<>
bool Less<int*>(int* x,int* y)
{
  return *x < *y;
}
int main()
{
  int a=10,b=20;
  Less(10,20); //匹配函数模板
  Less(&a,&b); //优先匹配int*特化模板
  return 0;
}

其实在函数特化这部分,真不如函数重载,函数模板特化可以少用。

bool Less(int* x,int* y)
{
  return *x < *y;
}

2)类模板特化

我们以 Less类 来举例:

template<class T1 , class T2>
struct Less
{
  bool operator()(const T1& x, const T2& y) const
  {
    return x < y;
  }
};

1. 全特化: 所有模板参数给出具体类型。


// 对Less类模板特化
template<>
struct Less<Date,Date>
{
  bool operator()(Date x, Date y) const
  {
    return x < y;
  }
};

2. 偏特化: 部分特化,一个继续是泛型,一个给出具体类型。

template<class T1>
struct Less<T1,int>
{
  bool operator()(T1 x, int y) const
  {
    return x < y;
  }
};

把指针泛型进一步提出来,也属于偏特化

template<class T1,class T2>
struct Less<T1*,T2*>
{
  bool operator()(const T1* x, const T2* y) const
  {
    return *x < *y;
  }
};

模板匹配原则:优先匹配现成的,有完全符合我的就用他,因为它很具体,里面函数体的执行也是量身定做。 让我想到一句要爱具体的人,不要爱抽象的人 因为具体的的人更懂我们哈哈,共勉!

6.类模板的声明定义分离

我们借思维导图来学习下:

声明定义分离有两种情况:

  1. 声明定义都放在头文件中(.h 或 .hpp),但在类模板里只声明,类模板外定义;
  2. 声明放在头文件(.h)————定义放在源文件(.cpp)

第一种情况: 在编译阶段,会展开头文件,调用该成员函数实例化,声明,会根据调用对象,生成找到定义地址位置的相关代码,再链接时,生成最终执行代码


第二种情况: 在(.cpp)文件中,就算包含了头文件,但没有实例化,在编译阶段就被编译器优化掉了,到了main函数调用的时候,链接时,就报错了。编译错误


第二种解决方案: 我们在(.cpp)文件中显式实例化一个任意类型的对象,类模板就会被保留下来,再到链接的时候整合代码,根据我们的调用生成新的类型的对象。对函数进行调用。


总结

本章重点就是讲解模板的使用,类模板更加重要,还有就是模板分离部分,很关键。思维导图持续优化~

看猫共勉,诸君加油~


相关文章
|
30天前
|
存储 C++
C++语言中指针变量int和取值操作ptr详细说明。
总结起来,在 C++ 中正确理解和运用 int 类型地址及其相关取值、设定等操纵至关重要且基础性强:定义 int 类型 pointer 需加星号;初始化 pointer 需配合 & 取址;读写 pointer 执向之处需配合 * 解引用操纵进行。
145 12
|
6月前
|
存储 负载均衡 算法
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
168 15
|
3月前
|
存储 算法 安全
c++模板进阶操作——非类型模板参数、模板的特化以及模板的分离编译
在 C++ 中,仿函数(Functor)是指重载了函数调用运算符()的对象。仿函数可以像普通函数一样被调用,但它们实际上是对象,可以携带状态并具有更多功能。与普通函数相比,仿函数具有更强的灵活性和可扩展性。仿函数通常通过定义一个包含operator()的类来实现。public:// 重载函数调用运算符Add add;// 创建 Add 类的对象// 使用仿函数return 0;
119 0
|
3月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
86 0
|
6月前
|
存储 算法 安全
企业员工数据泄露防范策略:基于 C++ 语言的布隆过滤器算法剖析[如何防止员工泄密]
企业运营过程中,防范员工泄密是信息安全领域的核心议题。员工泄密可能致使企业核心数据、商业机密等关键资产的流失,进而给企业造成严重损失。为应对这一挑战,借助恰当的数据结构与算法成为强化信息防护的有效路径。本文专注于 C++ 语言中的布隆过滤器算法,深入探究其在防范员工泄密场景中的应用。
110 8
|
6月前
|
编译器 C++
模板(C++)
本内容主要讲解了C++中的函数模板与类模板。函数模板是一个与类型无关的函数家族,使用时根据实参类型生成特定版本,其定义可用`typename`或`class`作为关键字。函数模板实例化分为隐式和显式,前者由编译器推导类型,后者手动指定类型。同时,非模板函数优先于同名模板函数调用,且模板函数不支持自动类型转换。类模板则通过在类名后加`&lt;&gt;`指定类型实例化,生成具体类。最后,语录鼓励大家继续努力,技术不断进步!
|
7月前
|
编译器 C++
㉿㉿㉿c++模板的初阶(通俗易懂简化版)㉿㉿㉿
㉿㉿㉿c++模板的初阶(通俗易懂简化版)㉿㉿㉿
|
7月前
|
安全 C++
【c++】模板详解(2)
本文深入探讨了C++模板的高级特性,包括非类型模板参数、模板特化和模板分离编译。通过具体代码示例,详细讲解了非类型参数的应用场景及其限制,函数模板和类模板的特化方式,以及分离编译时可能出现的链接错误及解决方案。最后总结了模板的优点如提高代码复用性和类型安全,以及缺点如增加编译时间和代码复杂度。通过本文的学习,读者可以进一步加深对C++模板的理解并灵活应用于实际编程中。
96 0
|
7月前
|
存储 安全 算法
深入理解C++模板编程:从基础到进阶
在C++编程中,模板是实现泛型编程的关键工具。模板使得代码能够适用于不同的数据类型,极大地提升了代码复用性、灵活性和可维护性。本文将深入探讨模板编程的基础知识,包括函数模板和类模板的定义、使用、以及它们的实例化和匹配规则。
|
10月前
|
安全 编译器 C++
【C++11】可变模板参数详解
本文详细介绍了C++11引入的可变模板参数,这是一种允许模板接受任意数量和类型参数的强大工具。文章从基本概念入手,讲解了可变模板参数的语法、参数包的展开方法,以及如何结合递归调用、折叠表达式等技术实现高效编程。通过具体示例,如打印任意数量参数、类型安全的`printf`替代方案等,展示了其在实际开发中的应用。最后,文章讨论了性能优化策略和常见问题,帮助读者更好地理解和使用这一高级C++特性。
324 4