C++超详细讲解模板的使用

目录
  • 一、函数模板
    • 1.1函数模板概念
    • 1.2 函数模板格式
    • 1.3 函数模板的原理
    • 1.4 函数模板的实例化
  • 二、类模板
    • 2.1 类模板的定义格式
    • 2.2类模板的实例化
  • 总结

一、函数模板

1.1函数模板概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

1.2 函数模板格式

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

返回值类型 函数名(参数列表){}

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

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

1.3 函数模板的原理

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

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

1.4 函数模板的实例化

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

隐式实例化:让编译器根据实参推演模板参数的实际类型

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);
  /*
  该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型
  通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有
一个T,
  编译器无法确定此处到底该将T确定为int 或者 double类型而报错
  注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要
背黑锅
  Add(a1, d1);
  */
  // 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化
  Add(a, (int)d);
  return 0;
}

显式实例化:在函数名后的<>中指定模板参数的实际类型

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

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

二、类模板

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

2.2类模板的实例化

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

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

总结

以上就是关于模板的初阶全部内容,后续还会更新,感谢大家的观看

到此这篇关于C++超详细讲解模板的使用的文章就介绍到这了,更多相关C++模板内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-06-16

C++将模板实现放入头文件原理解析

目录 写在前面 例子 原因 分析 解决方案 方案一 方案二 参考 写在后面 写在前面 本文通过实例分析与讲解,解释了为什么C++一般将模板实现放在头文件中.这主要与C/C++的编译机制以及C++模板的实现原理相关,详情见正文.同时,本文给出了不将模板实现放在头文件中的解决方案. 例子 现有如下3个文件: // add.h template <typename T> T Add(const T &a, const T &b); // add.cpp #include "

C++&nbsp;深入浅出探索模板

目录 非类型模板参数 模板特化 函数模板特化 类模板特化 全特化 偏特化 模板分离编译 模板的分离编译 解决方法 总结 非类型模板参数 模板参数分类类型形参与非类型形参. 类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称. 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用. 注意: 浮点数,类对象以及字符串是不允许作为非类型模板的. 非类型的模板参数必须在编译期就能确认结果. 模板特化 有时候,编译默认函数模板

C++可变参数模板的展开方式

文章目录 前言可变参数模板的定义参数包的展开递归函数方式展开逗号表达式展开enable_if方式展开折叠表达式展开(c++17) 总结 前言 可变参数模板(variadic templates)是C++11新增的强大的特性之一,它对模板参数进行了高度泛化,能表示0到任意个数.任意类型的参数.相比C++98/03这些类模版和函数模版中只能含固定数量模版参数的“老古董”,可变模版参数无疑是一个巨大的进步. 如果是刚接触可变参数模板可能会觉得比较抽象,使用起来会不太顺手,使用可变参数模板时通常离不开模

C++模板Template详解及其作用介绍

目录 1. 模板 2. 函数模板 2.1 函数模板概念 2.2 函数模板格式 2.3 函数模板原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 2.6声明定义分离 3. 类模板 3.1 类模板格式 3.2 类模板的实例化 3.3 类模板中函数放在类外进行定义时 4. 模板分离编译 4.1 什么是分离编译 4.2 模板的分离编译 5. 缺省值与返回值 6. 总结 1. 模板 首先模板分为函数模板和类模板 想到模板,就会联想到泛型编程 泛型编程:编写与类型无关的通用代码,是代码复用的一种手

c++分离讲解模板的概念与使用

目录 泛类编程 函数模板 函数模板的概念 函数模板的使用 函数模板的实例化 函数模板的匹配原则 类模板 类模板的定义格式 类模板的实例化 泛类编程 学习模板,首先我们需要了解一下什么是泛类编程 #include<iostream> using namespace std; int add(int a, int b) { return a + b; } double add(double a, double b) //这两个add构成了函数重载 { return a + b; } int mai

c++模板自定义数组

目录 1.自定义数组.hpp--文件 2.测试文件 前言: 制造通用模板,创建自定义的数组, 一个数组,里面有这么几个属性,数组容量,数组元素个数,数组本身内存地址,这几个数据都是定义私有类型,提供有参构造,让用户可以构造出这个数组对象.下面是有参构造和拷贝构造和析构函数还有operator=重载的代码 在前面类模板中成员函数创建有这个主意问题,最好的办法就是把类模板写在一个hpp的文件中,不要拆开写成多个文件 1.自定义数组.hpp--文件 #pragma once #include<iost

C++11中模板隐式实例化与显式实例化的定义详解分析

目录 1. 隐式实例化 2. 显式实例化声明与定义 3. 显式实例化的用途 1. 隐式实例化 在代码中实际使用模板类构造对象或者调用模板函数时,编译器会根据调用者传给模板的实参进行模板类型推导然后对模板进行实例化,此过程中的实例化即是隐式实例化. template<typename T> T add(T t1, T2) { return t1 + t2; } template<typename T> class Dylan { public: T m_data; }; int ma

C++模板全方位深入解读

目录 1.泛型编程 2.函数模板 概念 函数模板的格式 函数模板的原理 函数模板的实例化 隐式实例化 显式实例化 模板参数的匹配原则 3.类模板 (1) 类模板的定义格式 (2) 类模板的实例化 4.非类型模板参数 5.模板特化 (1)函数模板的特化 (2)类模板的特化 全特化 偏特化 6.模板的分离编译 问题分析 1.泛型编程 如何实现一个通用的交换函数? 这点函数重载可以做到,比如一下Swap函数的重载,分别重载了俩种不同参数类型的Swap void Swap(int& x, int&

如何C++使用模板特化功能

目录 前言: 1.函数模板的特化 2.类模板的特化 前言: 通过定义模板,使得函数或者类不依赖于特定的类型,这样大幅提升了代码的复用性. 然而,不管是类模板还是函数模板,对所有的类型都是采用相同的处理方式(同一份代码).为此,C++提出了“模板特化的概念”,对特定类型提供模板的改造. 比如,对于函数模板来说,可以通过特化指定特定的类型,针对此特定类型对函数体内容进行重写,使得函数对特定类型实现特定功能. 注意: 按照语法,对函数模板和类模板进行特化后,就变为普通函数和普通的类,而不再是模板. 1

深入分析C++模板特化与偏特化

1.模板特化 1.1概述 模板特化(template specialization)不同于模板的实例化,模板参数在某种特定类型下的具体实现称为模板的特化.模板特化有时也称之为模板的具体化,分别有函数模板特化和类模板特化. 1.2函数模板特化 函数模板特化是在一个统一的函数模板不能在所有类型实例下正常工作时,需要定义类型参数在实例化为特定类型时函数模板的特定实现版本.查看如下例子. #include <iostream> using namespace std; template<type

C#开发之微信小程序发送模板消息功能

步骤一:获取模板ID 有两个方法可以获取模版ID 通过模版消息管理接口获取模版ID 在微信公众平台手动配置获取模版ID 步骤二:页面的 <form/> 组件,属性report-submit为true时,可以声明为需发模板消息,此时点击按钮提交表单可以获取formId,用于发送模板消息.或者当用户完成支付行为,可以获取prepay_id用于发送模板消息. 步骤三:调用接口下发模板消息 今天重要的说第三步怎么实现,前面的步骤比较简单就略过. ----------------------------

laravel 5 实现模板主题功能

众所周知,laravel渲染模板是通过View::make()实现的,需要显式指定模板文件路径: 复制代码 代码如下: function index() {     return View::make('index.index'); } 既然这样,我们就可以自己实现模板主题功能,我们只需要将模板文件放到一个主题名称对应的目录里就行,比如默认主题为 default 的话,我们就这样写: 复制代码 代码如下: function index() {     return View::make('def

PHP实现简单的模板引擎功能示例

本文实例讲述了PHP实现简单的模板引擎功能.分享给大家供大家参考,具体如下: php web开发中广泛采取mvc的设计模式,controller传递给view层的数据,必须通过模板引擎才能解析出来.实现一个简单的仅仅包含if,foreach标签,解析$foo变量的模板引擎. 编写template模板类和compiler编译类.代码如下: <?php namespace foo\base; use foo\base\Object; use foo\base\Compiler; /** * */ c

laravel 5 实现模板主题功能(续)

在之前一篇文章中我介绍了通过定义Response宏的方式来实现动态改变模板文件路径以实现主题功能: laravel实现模板主题功能,但后来我发现这种方法有个弊端,在模板中使用@extends必须显式指定模板路径,这可能造成混乱,我决定还是改变思想,主题和主题之间应该是完全隔离的,不存在就是不存在,不要自动去另外的主题中寻找替代的模板. 而原来定义response宏的方式可以实现,但我决定使用更加规范的方法. laravel的View类里有一个方法 View::addNamespace ,这个方法

Python实现的简单模板引擎功能示例

本文实例讲述了Python实现的简单模板引擎功能.分享给大家供大家参考,具体如下: #coding:utf- 8 __author__="sdm" __author_email='sdmzhu3@gmail.com' __date__ ="$2009-8-25 21:04:13$" '' ' pytpl 类似 php的模板类 '' ' import sys import StringIO import os.path import os #模 板的缓存 _tpl_c

Python编程之微信推送模板消息功能示例

本文实例讲述了Python微信推送模板消息功能.分享给大家供大家参考,具体如下: 官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432 具体代码如下: #!/usr/bin/env python #-*- coding: utf-8 -*- import httplib import json import MySQLdb #从数据库中获取access_token access_token="&quo

C#微信接口之推送模板消息功能示例

本文实例讲述了C#微信接口之推送模板消息功能.分享给大家供大家参考,具体如下: public string SendTempletMessge() { string strReturn = string.Empty; try { #region 获取access_token string apiurl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=你的appid&secr

php实现QQ小程序发送模板消息功能

QQ小程序群里有伙伴要发送模板消息的代码,所以今天给大家分享QQ小程序模板消息发布,绝对一步一步带着大家走,每个细节都讲到. 今天先用php简单写一下,有空了再写java的. 首先创建一个空项目: 因为QQ小程序没有编译器,先用微信小程序创建. 然后新建一个页面,直接上html代码: <form bindsubmit="form_submit" report-submit="true"> <button formType="submit&

微信小程序实现发送模板消息功能示例【通过openid推送消息给用户】

本文实例讲述了微信小程序实现发送模板消息功能.分享给大家供大家参考,具体如下: 一.获取access_token access_token是接口调用的凭证,目前有效期为两个小时,需要定时刷新,重复获取将导致上次获取的access_token失效.(注:不建议每次调用需要access_token的接口,都去重新获取access_token,会导致失败) 获取access_token的接口地址: https://api.weixin.qq.com/cgi-bin/token?grant_type=c