• c++学习记录(四)


    1、函数模版

    模版是c++参数多态的工具,模版一般有类模板和函数模版,使得类中的某些数据或者函数成员可以支持任意类型的参数。同时返回值也是一样的,可以取得任意类型。

    通过使用模版:

    能够使程序员编写和类型无关的代码,比如下面编写一个经典的交换代码,默认的话我们需要指定参数类型,例如整形,那我们就只能对整数类型进行交换,这样我们如果要对浮点数进行交换就很蛮烦,使用模版就可以实现这个与类型无关。

    1、函数模版的概念

    函数模版的使用在上面已经介绍过了,这里不在赘述,下面是函数模版的基本语法:

    template
    函数声明或定义
    
    • 1
    • 2

    说明如下:

    • template — 声明创建模板
    • typename — 表面其后面的符号是一种数据类型,可以用class代替
    • T — 通用的数据类型,名称可以替换,通常为大写字母

    2、函数模版例子

    下面用一个交换函数来用模版的方式来进行表达:

    代码如下:

    template<typename T>
    void mySwap(T& a, T& b)
    {
    	T temp = a;
    	a = b;
    	b = temp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用模版有两种方式可以进行,如下所示:
    在这里插入图片描述
    使用模版进行比较效果如下:
    在这里插入图片描述
    当然这里还是要相同类型的参数进行比较,不然还是会报错的:
    在这里插入图片描述

    因此可以看出,使用函数模版的优势在于:

    • 函数模板利用关键字 template
    • 使用函数模板有两种方式:自动类型推导、显示指定类型
    • 模板的目的是为了提高复用性,将类型参数化

    3、使用函数模版来实现多种排序

    下面来使用函数模版实现不同类型数据的排序,这里还是用最经典的冒泡排序的方式来实现,根据之前介绍的冒泡排序需要我们进行逐一的筛选然后替换,所以这里需要两个函数模版,如下所所示:
    在这里插入图片描述
    代码如下:

    template<typename T>
    void mySwap(T &a, T&b)
    {
    	T temp = a;
    	a = b;
    	b = temp;
    }
    template<typename T>
    void mySort(T arr[], int len)
    {
    	for (int i = 0; i < len; i++)
    	{
    		int max = i; //最大数的下标
    		for (int j = i + 1; j < len; j++)
    		{
    			if (arr[max] < arr[j])
    			{
    				max = j;
    			}
    		}
    		if (max != i) //如果最大数的下标不是i,交换两者
    		{
    			mySwap(arr[max], arr[i]);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    下面是测试的函数:
    在这里插入图片描述
    运行结果如下所示:
    在这里插入图片描述

    2、类模板

    1、类模板的概念

    类模板的作用为:

    • 建立一个通用类,类中的成员 数据类型可以不具体制定,用一个虚拟的类型来代表。

    使用类模板的语法如下所示:

    template
    • 1
    • 2

    参数说明如下:

    • template — 声明创建模板
    • typename — 表面其后面的符号是一种数据类型,可以用class代替
    • T — 通用的数据类型,名称可以替换,通常为大写字母

    2、类模板使用示例

    下面是一个类模板的使用示例,如下所示:
    在这里插入图片描述
    代码如下:

    template<typename NameType, typename AgeType>
    class Person
    {
    public:
    	Person(NameType name, AgeType age)
    	{
    		this->mName = name;
    		this->mAge = age;
    	}
    	void showPerson()
    	{
    		cout << "name: " << this->mName << " age: " << this->mAge << endl;
    	}
    public:
    	NameType mName;
    	AgeType mAge;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    指定参数类型,调用这个模版
    在这里插入图片描述
    运行结果如下所示:
    在这里插入图片描述

    3、类模板和函数模版的区别

    这里类模板与函数模板区别主要有两点:

    1. 类模板没有自动类型推导的使用方式
    2. 类模板在模板参数列表中可以有默认参数

    在这里插入图片描述

    4、类模板中成员函数的创建时机

    类模板中成员函数的规则如下所示,相比普通类中而言:

    • 普通类中的成员函数一开始就可以创建
    • 类模板中的成员函数在调用时才创建

    下面是一个示例:
    在这里插入图片描述
    下面是使用过程的影响,这里如果调用第二个成员函数就会报错
    在这里插入图片描述
    这是因为:类模板中的成员函数,并不是一开始就创建的,而是在模板调用时再生成
    在这里插入图片描述
    代码如下:

    #include
    using namespace std;
    #include
    
    class Person1
    {
    public:
    	void showPerson1()
    	{
    		cout << "Person1 show" << endl;
    	}
    };
    class Person2
    {
    public:
    	void showPerson2()
    	{
    		cout << "Person2 show" << endl;
    	}
    };
    
    template<class T>
    class MyClass
    {
    public:
    	T obj;
    	void fun1() { obj.showPerson1(); }
    	void fun2() { obj.showPerson2(); }
    };
    
    void test01()
    {
    	MyClass<Person1> m;
    	m.fun1();
    	m.fun2();
    }
    
    int main() 
    {
    	test01();
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    5、类模板对象做函数参数

    类模板实例化出的对象,向函数传参一共有三种传入方式:

    1. 指定传入的类型 — 直接显示对象的数据类型
    2. 参数模板化 — 将对象中的参数变为模板进行传递
    3. 整个类模板化 — 将这个对象类型 模板化进行传递

    下面举例来表述这个方式,首先还是先新建一个类模版:

    template<class NameType, class AgeType = int>
    class Person
    {
    public:
    	Person(NameType name, AgeType age)
    	{
    		this->mName = name;
    		this->mAge = age;
    	}
    	void showPerson()
    	{
    		cout << "name: " << this->mName << " age: " << this->mAge << endl;
    	}
    public:
    	NameType mName;
    	AgeType mAge;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    类模板进行函数参数的传递一共有三种方式,如下所示:

    • 指定参数类型和参数名称直接传入(这种跟普通的参数传入没什么区别):
      在这里插入图片描述
    • 将参数模版化传入
      在这里插入图片描述
    • 直接将整个类模版化
      在这里插入图片描述

    一般第一种比较常用,和普通的传入参数的方法也是一样的。

    3、STL

    1、STL的基本概念

    主要是为了避免重复造轮子的繁琐工作才会产生STL这样的方法,C++的面向对象泛型编程思想,目的就是复用性的提升,大多情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作,因此为了建立数据结构和算法的一套标准,诞生了STL

    2、STL介绍

    STL从大的框架上主要包含:

    • STL(Standard Template Library,标准模板库)
    • STL 从广义上分为: 容器(container) 算法(algorithm) 迭代器(iterator)
    • 容器算法之间通过迭代器进行无缝连接。
    • STL 几乎所有的代码都采用了模板类或者模板函数

    STL大体分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

    1. 容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据。
    2. 算法:各种常用的算法,如sort、find、copy、for_each等
    3. 迭代器:扮演了容器与算法之间的胶合剂。
    4. 仿函数:行为类似函数,可作为算法的某种策略。
    5. 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。
    6. 空间配置器:负责空间的配置与管理。

    STL中容器、算法、迭代器

    • STL容器就是将运用最广泛的一些数据结构实现出来

    常用的数据结构:数组, 链表,树, 栈, 队列, 集合, 映射表 等
    这些容器分为序列式容器关联式容器两种:
    序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置。
    关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系

    • 有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms)

    算法分为:质变算法非质变算法
    质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等
    非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等

    • 迭代器:容器和算法之间粘合剂

    提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。
    每个容器都有自己专属的迭代器
    迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针

    迭代器种类:

    种类功能支持运算
    输入迭代器对数据的只读访问只读,支持++、==、!=
    输出迭代器对数据的只写访问只写,支持++
    前向迭代器读写操作,并能向前推进迭代器读写,支持++、==、!=
    双向迭代器读写操作,并能向前和向后操作读写,支持++、–,
    随机访问迭代器读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器读写,支持++、–、[n]、-n、<、<=、>、>=

    常用的容器中迭代器种类为双向迭代器,和随机访问迭代器

    3、容器

    下面来通过示例查看这三个比较重要概念的额应用情况,这三者的名称如下所示:

    容器: vector
    算法: for_each
    迭代器: vector::iterator

    下面举一个容器中输入数据然后遍历输出的例子,可以看出其实这个容器还是很像一个数组的,或者python中的列表。
    在这里插入图片描述
    输出结果如下:
    在这里插入图片描述
    代码如下

    #include 
    #include 
    
    void MyPrint(int val)
    {
    	cout << val << endl;
    }
    
    void test01() 
    {
    	vector<int> v;//创建一个容器
    
    	//向容器中放数据
    	v.push_back(10);
    	v.push_back(20);
    	v.push_back(30);
    	v.push_back(40);
    
    	vector<int>::iterator pBegin = v.begin();//获取元素开头和结尾方便后续使用
    	vector<int>::iterator pEnd = v.end();
    
    	cout << "第一种遍历" << endl;
    	while (pBegin != pEnd) 
    	{
    		cout << *pBegin << endl;
    		pBegin++;
    	}
    
    	cout << "第二种遍历" << endl;
    	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) 
    	{
    		cout << *it << endl;
    	}
    	cout <<"第三种遍历"<< endl;
    	for_each(v.begin(), v.end(), MyPrint);
    }
    
    int main() {
    
    	test01();
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
  • 相关阅读:
    【Java-LangChain:使用 ChatGPT API 搭建系统-11】用 ChatGPT API 构建系统 总结篇
    C# 第七章『I/O数据流』◆第5节:数据流—StreamWriter类
    图论27(Leetcode721账户合并)
    MATLAB常用绘图函数的使用
    mysql5.7安装配置教程(一看就会)
    docker安装nacos
    Flume配置1——基础案例
    C++函数对象包装器function类详解
    用简单例子讲清楚webgl模板测试
    Linux网络编程(五)
  • 原文地址:https://blog.csdn.net/m0_51220742/article/details/125652020