模板简要介绍,C++读书笔记

2014年2月3日   内容整理自《程序设计教程:  用C++语言编程 第三版》 陈家骏  郑滔

---------------------------------------------------------------------------------------------------------------------------------

(一)函数模板

1)类属函数和类属类

  • 类属函数是指一个函数能够对不同类型的数据(参数)完成相同的操作。
  • 类属类是指一个类的成员类型可变,从而可以用它描述不同种类的对象。

C++是一个静态类型语言,它提供了多种实现类属函数的途径,其中包括:

  • 宏定义
  • 指针类型
  • 函数模板

其中宏定义虽然能实现类属函数的效果,但它毕竟不是函数,而只是在编译之前的文字替换,因此下面介绍指针参数和函数模板实现的类属函数。

2)用指针参数实现类属函数

#include<iostream>
using namespace std;
//用指针参数实现类属的排序函数(框架)


void sort(
        
        //1.先定义一个void* 类型的形参base,使得它能够接受任意待排序数组的首地址
        void *base,
        //2.count参数用于获得数组元素的个数
        unsigned int count,
        //3.element_size用于每个数据元素的尺寸
        unsigned int element_size,
        //4.最后定义一个函数指针类型的形参cmp,它从调用者处获得一个函数,这个函数功能是比较两个数组元素的大小
        bool (*less_than)(const void*,const void*)
        
        ){
    
    //(1)取第i个元素,i从0到count-1,下面是第i个元素的首地址
    (char*)base+i*element_size;
    
    //(2)比较第i个和第j个元素的大小:首先分别计算i和J的首地址,然后调用cmp指向的函数来比较这两个地址上元素的大小
    (*less_than)(
            (char*)base+i*element_size,(char*)base+j*element_size
            )//传入i和j的地址
            
    
    //(3)交换i和j,逐个字节交换这两个地址上的元素
    char* p1=(char*)base+i*element_size;//p1是i的地址
    char* p2=(char*)base+j*element_size;//p2是j的地址

    for(int k=0;k<element_size;k++){
        char temp=p1[k];
        p1[k]=p2[k];
        p2[k]=temp;
    }//逐个字节交换地址上的元素
  
}


int main(){
   
   return 0;
}

-------------------------------------------------------------------------------------------------------------------------------

下面的程序片段是利用上面定义的排序函数分别对int、double、以及A类型的数组进行排序

//比较int类型的元素大小
bool int_less_than(const void* p1,const void* p2){
    if( *(int *)p1<*(int *)p2  )
        return true;
    else
        return false;
}


//比较double类型的元素大小
bool double_less_than(const void* p1,const void* p2){
    if( *(double *)p1<*(double *)p2  )
        return true;
    else
        return false;
}

//比较A类型的元素大小
bool A_less_than(const void* p1,const void* p2){
    if( *(A *)p1<*(A *)p2  )
        return true;
    else
        return false;
}

---------------------------------------------------------------------------------------------------------------------------------

用指针实现类属函数的不足之处在于:除了数组首地址和数组元素个数外,需要定义额外的参数(元素尺寸和比较函数),并且要进行大量的指针运算,这不仅使得实现比较麻烦,而且使得程序易读性差和容易出错。另外,用指针实现类属函数也不便于编译程序进行类型检查。。

3)用函数模板实现类属函数

C++中,实现类属函数的另外一种方法是用函数模板,function template是指带有类型参数的函数定义,格式如下:

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

例子:

//用模板实现类属的排序函数框架
template <class T>//T是数组的元素类型,可以是int、double、A。。。
void sort(T elements[],unsigned int count){
    //取第i个元素
    elements[i];
    //比较第i个和第j个元素的大小
    elements[i]<elements[j]
    
    //交换第i和第j个元素
    T temp=elements[i];
    elements[i]=elements[j];
    elements[j]=temp;
}//sort
...
int a[100];
sort(a,100);//对int类型数组进行排序
double b[200];
sort(b,200);//对double类型数组进行排序
A c[300];
sort(c,300);//对A类型数组进行排序

4)函数模板的实例化

  • 函数模板可以隐式实例化,也可以显式实例化
  • 类模板只能显式实例化

显式实例化格式:

//模板函数max的声明
template <class T>
T max(T a,T b){
    
     return a>b?a:b;    
    
}
//模板函数max的调用(显式)
max<double>(1.4,3.5);

5)除了类型参数外,模板也可以带有非类型参数

#include<iostream>
using namespace std;

//第一个参数T是类型参数,取值为(int,double,float等),第二个参数是普通参数
//模板函数定义
template <class T,int size>
void function(T t){
    T temp[size];
}
//模板函数调用示例
int main(){
    function<float,10>(8.9);
    //T类型为float,size为10的,参数为(float t)且取t=8.9的函数
   return 0;
}

(二)类模板

如果一个类的成员类型可变,则该类成为类属类。在C++中,类属类一般用类模板实现。

类模板(class template)是指带有类型参数的类定义

1)格式

template <class T1,class T2,...,class Tn>
class <类名>{
    ...
};
//对于在类内声明,类外定义的成员函数,应采用如下格式
template <class T1,class T2,...,class Tn>
<返回值类型> <类名><T1,T2,...Tn>::<成员函数名>(<参数列表>){
    ...
}

2)类模板示例练习01(自己动手打一遍才能记住)

1.模板类的定义

//定义一个可以表示各种元素的Stack类
template <class T>
class Stack{
    //private数据成员
    T array[100];//定义一个元素类型为T的,长度为100的数组array
    int top;
    //public功能函数
public:
    Stack(){ top=-1;}//构造函数
    void push(const T &x);//在类内声明,等一会需要再类外定义的成员函数,传入一个T类型的数据压入栈中
    void pop(T &x);//类型为T的元素x退栈
};

2.类外函数的定义

template <class T>
void Stack<T>::push(const T &x) {
    ...
}

template <class T>
void Stack<T>::pop(const T &x){
    ...
}

3.在main中使用该模板类的格式示例

//模板类调用示例
int main(){
   Stack<int> S1;//T被实例化为int,创建了一个类的对象S1
   int x;
   S1.push(10);
   S1.pop(x);
    
   Stack<double> S2;
   double y;
   S2.push(4.4);
   S2.pop(y);
   
   Stack<A>  S3;
   A m,n;
   S3.push(m);
   S3.pop(n);
   
   return 0;
}

3)类模板示例练习02

1.模板类的定义

template <class T,int size>//同时带有类型参数和非类型参数的模板类
class Stack{
    T array[size];//每个元素为T类型,大小为size的数据成员
    int top;
public:
    Stack(){ top=-1;}
    void push(const T &x);
    void pop(T &x);
};

2.类外函数的定义

template <class T,int size>
void Stack<T,size>::push(const T &x){
    
}

template <class T,int size>
void Stack<T,size>::pop(T &x){
    
}

3.在main中使用该模板类的格式示例

//模板类调用示例
int main(){
    
   Stack<int,100> S1;//创建一个最多有100个int类型的元素所构成的Stack对象
   Stack<double,44> S2;//创建一个最多有44个double类型的元素所构成的Stack对象

   return 0;
}

(三)类模板分文件编写(.h和.cpp)

1)第一种方式:直接包含源文件.cpp

原因:在.h中只有声明,对于模板类来说是没有创建的,所以编译器会找不到实例;假如直接“#include xx.cpp”由于该.cpp文件中已经包含了.h,所以代码是完整的。

2)第二种方式:(更常用)将源文件和头文件的内容写到一起,将后缀名改为.hpp

-------------------------------------------------------

  写在最后,这几天零零散散看了C++里面的模板和容器,因为这章比较难,看The Cherno就看不太懂了,视频换成了b站的黑马程序员,加上读教材,磨了好几天终于有一点点明白了,OK。因为宅家太穷又去打了5天零工,每天11点睡5点半起床,洗把脸就得骑车去卡点上班。然后,如果说Cherno的C++系列是适合有编程经验的精华教程,精灵密道,那么黑马就是适合小白提升能力的高速大马路。黑马的那个老师用的软件是什么不知道,就是看起来非常舒服,小巧便捷,启动快,截图如下,感觉学编程这样搞,整洁、有秩序、有逻辑,会让自己的认知加速。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/367784.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

苹果的ipad可能会缓存vue项目的数据或者pinia数据

如果你发现开发的vue项目在ipad上出现了异常&#xff0c;比如数据出现NaN的情况&#xff0c;或者computed计算属性没生效&#xff0c;或者pinia里面的数据没生效&#xff0c;可能就是ipad浏览器safari缓存了数据导致的&#xff0c;只需要清空safari里面缓存的数据就可以了&…

(java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~

目录 冒泡排序(BubbleSort)&#xff1a; 代码详解&#xff1a; 冒泡排序的优化&#xff1a; 选择排序(SelectSort)&#xff1a; 代码详解&#xff1a; 插入排序&#xff08;InsertSort&#xff09;&#xff1a; 代码详解&#xff1a; 希尔排序(ShellSort)&#xff1a; 法一…

深度学习图像分类相关概念简析+个人举例1(ANN相关概念与计算)

&#xff08;1&#xff09;神经网络&#xff1a;英文全称Artificial Neural Network&#xff0c;简称为ANN。 神经网络是一种模仿人脑神经元结构和功能的人工智能模型。它由多个神经元&#xff08;也称节点、单元&#xff09;组成&#xff0c;每个神经元通过计算输入和权重的线…

从零开始复现GPT2(六):生成代码的实现

源码地址&#xff1a;https://gitee.com/guojialiang2023/gpt2 GPT2 模型文本生成配置生成框架文本生成类实现文本生成代码 模型 文本生成 配置 class GenerateConfig(object):def __init__(self,seq_len: int,nucleus_prob: float,use_gpu: bool):self.seq_len seq_lenself…

【C/C++ 10】扫雷小游戏

一、题目 写一个扫雷小游戏&#xff0c;每次输入一个坐标&#xff0c;若该处是地雷&#xff0c;则游戏失败&#xff0c;若该处不是地雷&#xff0c;则显示周围地雷数量&#xff0c;若扫除全部非地雷区域&#xff0c;则扫雷成功。 二、算法 设置两张地图&#xff08;二维数组&…

手把手教你开发Python桌面应用-PyQt6图书管理系统-主界面UI设计实现

锋哥原创的PyQt6图书管理系统视频教程&#xff1a; PyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~_哔哩哔哩_bilibiliPyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~共计24条视频&…

移远(Quectel)物联网通信解决方案

一、方案简介 无线通信模块是具备无线通信的电路模块&#xff0c;它能通过无线连接传输数据&#xff0c;能识别分析主控制器发来的命令&#xff0c;控制节点设备的工作&#xff0c;或者向主控制器发送当前节点设备的工作状态。 市面上常用的无线通信模组包括蓝牙模组、WLAN模…

2024年【上海市安全员B证】最新解析及上海市安全员B证复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 上海市安全员B证最新解析根据新上海市安全员B证考试大纲要求&#xff0c;安全生产模拟考试一点通将上海市安全员B证模拟考试试题进行汇编&#xff0c;组成一套上海市安全员B证全真模拟考试试题&#xff0c;学员可通过…

算法练习-二叉树的节点个数【完全/普通二叉树】(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;二叉树 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。且所在课程未提供测试平台&#xff0c;故实现代码主要为自行测试的那种&#xff0c;以下内容均为个人笔记&#xff0c;旨…

ubuntu22.04 安装部署01:禁用内核更新

一、前言 ubunut22.04系统安装以后&#xff0c;内核更新会导致各种各样的问题&#xff0c;因此锁定初始安装环境特别重要&#xff0c;下面介绍如何锁定内核更新。 二、操作方法 2.1 查看可用内核 dpkg --list | grep linux-image dpkg --list | grep linux-headers dpkg --…

STM32--USART串口(2)串口外设

一、USART简介 可配置数据位&#xff1a;不需要校验就是8位&#xff0c;需要校验就选9位&#xff1b; 停止位&#xff1a;决定了帧的间隔; STM32F103C8T6USART&#xff1a;USART1挂载在APB2总线上&#xff0c;USART2和USART3挂载在APB1总线上&#xff1b; 二、USART框图 TXE…

Python中使用Opencv-python库绘制直线、矩形、圆、文本

Python中使用Opencv-python库绘制直线、矩形、圆、文字 在Python中使用Opencv-python绘制直线、矩形、圆、文本非常简单&#xff0c;分别使用到line、rectangle、circle、putText这几个函数&#xff0c;具体可以参考https://docs.opencv.org/4.9.0/d6/d6e/group__imgproc__dra…

如何部署Node.js服务并实现无公网ip远程访问本地项目【内网穿透】

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

【C++】类与对象(三)—运算符重载|const成员函数|取地址及const取地址操作符重载

前言 运算符重载&#xff0c;自增自减运算符重载&#xff0c;const成员函数&#xff0c;取地址及const取地址操作符重载 文章目录 一、运算符重载自增和自减运算符重载 二、const 成员函数三、取地址及const取地址操作符重载&#xff08;了解即可&#xff09; 一、运算符重载 运…

P1967 [NOIP2013 提高组] 货车运输

[NOIP2013 提高组] 货车运输 题目背景 NOIP2013 提高组 D1T3 题目描述 A 国有 n n n 座城市&#xff0c;编号从 1 1 1 到 n n n&#xff0c;城市之间有 m m m 条双向道路。每一条道路对车辆都有重量限制&#xff0c;简称限重。 现在有 q q q 辆货车在运输货物&#x…

Unity Meta Quest MR 开发(三):Scene API 配置+实现虚拟与现实之间的碰撞

文章目录 &#x1f4d5;教程说明&#x1f4d5; Scene 配置⭐开启场景理解功能和应用访问空间数据的权限⭐OVRSceneManager⭐制作 Plane Prefab 和 Volume Prefab⭐运行场景⭐添加透视材质 &#x1f4d5;虚拟与现实物体的碰撞&#xff08;弹球 Demo&#xff09;&#x1f4d5;Mes…

【JavaSE篇】——继承

目录 &#x1f393;继承 ✅为什么需要继承 ✅继承概念 ✅继承的语法 ✅父类成员访问 &#x1f6a9;子类中访问父类的成员变量 1. 子类和父类不存在同名成员变量的情况 2. 子类和父类成员变量同名 &#x1f6a9;子类中访问父类的成员方法 1. 成员方法名字不同 2. 成员…

MyBatis常见面试题汇总

说一下MyBatis执行流程&#xff1f; MyBatis是一款优秀的基于Java的持久层框架&#xff0c;它内部封装了JDBC&#xff0c;使开发者只需要关注SQL语句本身&#xff0c;而不需要花费精力去处理加载驱动、创建连接等的过程&#xff0c;MyBatis的执行流程如下&#xff1a; 加载配…

车载测试Vector工具——基于DoIP的ECU/车辆的连接故障排除

车载测试Vector工具——基于DoIP的ECU/车辆的连接故障排除 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和…

计算huggingface模型占用硬盘空间的实战代码

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…