C++ 提高编程 黑马教程(05)

1.模板

(1)简介

/** C++提高编程* 本阶段主要针对C++泛型编程 和 STL技术 做详细讲解,探讨C++更深层的使用** 1.模板* 概念:模板就是建立通用的模具,大大提高复用性** 特点:*      模板不可以直接使用,它只是一个框架*      模板的通用并不是万能的*/
int main() {return 0;
}

(2)函数模板

/** 函数模板* 建立一个通用函数,其函数返回值类型和形参类型可以不具体指定,用一个虚拟的类型来代表。* 语法:template<typename T>*      函数声明或者定义*      解释:template--声明创建模板*          tempname --表明其后面的符号是一种数据类型,可用class替换*          T --通用的数据类型,名称可以替换,通常为大写字母**  隐式模板 mySwap(a,b);*  显示模板 mySwap<int>(a,b);** 注意事项*      自动类型推导,需要推导出一致的数据类型T,才可以使用*      模板必须要确定出T的数据类型,才可以使用。*/
//函数模板
template<typename T> //声明一个模板,告诉编译器后面代码中紧跟着的T不要报错,T是一个通用数据类型
void mySwap(T &a,T &b){T temp=a;a=b;b=temp;
}
template<typename T>
void func(){cout<<"fun 调用"<<endl;
}
void test01(){int a=10;int b=20;//1.自动类型推导mySwap(a,b);//2.显示指定类型mySwap<int>(a,b);cout<<"a="<<a<<endl;cout<<"b="<<b<<endl;
}
int main() {test01();func<int>();return 0;
}

(3)函数模板案例

/** 函数模板案例** 描述:*      利用函数模板封装一个排序的函数,可以对不同数据类型素组进行排序*      排序规则从大到小,排序算法为选择排序*      分别利用char数组和int数组进行测试**/template<class 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++){//认定的最大值比遍历出的数组要小,说明j下表的数值大if(arr[max]<arr[j]){max=j;}}if(max!=i){T temp=arr[max];arr[max]=arr[i];arr[i]=temp;}}
}//冒泡排序
template<typename T>
void sayArray(T arr[],int len) {cout << "数组元素为:" << sizeof(arr) <<endl;for (int i = 0; i < len; i++) {cout << arr[i] << endl;}
}void test01() {char charArr[]="abcdef";int num=sizeof (charArr)/ sizeof(char);mySort(charArr,num);sayArray(charArr,num);
}int main() {test01();return 0;
}

(4)普通模板和函数模板的调用规则

/** 普通函数和函数模板的调用规则*      如果函数模板和普通函数都可以实现,优先调用普通函数*      可以通过空模板参数列表来强制调用函数模板  myPrint<>(2,2);*      函数模板也可以发生重载*      如果函数模板可以产生更好的匹配,优先调用函数模板*/void myPrint(int a, int b) {cout << "调用的普通函数" << endl;
}template<typename T>
void myPrint(T a, T b) {cout << "调用的模板" << endl;
}//函数模板 重载
template<typename T>
void myPrint(T a, T b, int) {cout << "调用的模板" << endl;
}int main() {myPrint(1, 2);//空模板参数列表,强制调用函模板myPrint<>(2, 2);//如果函数模板产生更好的匹配,优先调用函数模板myPrint('1', 'a');return 0;
}

(5)模板的局限性

/** 模板的局限性* 模板的通用性并不是万能的* 有些特定数据类型,需要用具体化方式做特殊实现*/class Person {
public:string name;int age;Person(string name, int age) {this->name = name;this->age = age;}bool operator==(Person &p) {cout<<"operator== 函数被调用了"<<endl;if (this->name == p.name && this->age == p.age) {return true;} else {return false;}}
};//对比两个数据是否相等
template<class T>
bool myCompare(T &a, T &b) {if (a == b) {return true;} else {return false;}
}void test01() {int a = 20;int b = 20;bool ret = myCompare(a, b);if (ret) {cout << "a==b" << endl;} else {cout << "a!=b" << endl;}
}void test02() {Person p1("张三", 10);Person p2("李四", 10);bool ret = myCompare(p1, p2);cout << "p1==p2:" << ret << endl;
}int main() {test01();test02();return 0;
}

(7)类模板

(1)类模板开胃菜

/** 类模板* 类模板语法:* 建立一个通用类,类中的成员 数据类型可以不具体定制,用一个虚拟的类型来代表。** 语法:*      template<typename T>*      类* 解释:*      template -- 声明创建模板*      typename -- 表明其后面的符号是一种数据类型,可以用class'代替*      T -- 通用的数据类型,名称可以替换,通常为大写字母**///类模板
template<class nameType, class ageType>
class Person {
public:nameType name;ageType age;Person(nameType name, ageType age) {this->name = name;this->age = age;}void showPerson() {cout << "name=" << this->name << ";age=" << age << endl;}
};void test01() {Person<string, int> p1("孙大圣", 28);p1.showPerson();Person p2("孙大圣2", "282");p2.showPerson();
}int main() {test01();return 0;
}

(2)类模板与函数模板的区别

/** 类模板和函数模板区别*      1.类模板没有自动类型推导的使用  自己使用的版本为C++20,以支持自动推导*      。类模板在模板参数列表中可以有默认参数**///类模板与函数模板的区别
template<class nameType, class ageType=string>
class Person {
public:nameType name;ageType age;Person(nameType name, ageType age) {this->name = name;this->age = age;}void showPerson() {cout << "name=" << this->name << ";age=" << age << endl;}
};//1.类模板没有自动类型推导使用方式
void test01() {Person p1("孙悟空", 1000);
}//2.类模板在模板参数列表中可以有默认参数
void test02() {Person p2("aaa", 123);p2.showPerson();Person p3("bbb", '234');p3.showPerson();
}int main() {test02();return 0;
}

(3)类模板中成员函数创建时机

/** 类模板中成员函数创建时机** 类模板中成员函数和普通类中成员函数创建时机是有区别的*      普通泪中的成员函数一开始就可以创建*      类模板中的成员函数在调用时候才创建**/class Person1 {
public:void showPerson1() {cout << "Person1" << endl;}
};class Person2 {
public:void showPerson2() {cout << "Person2 show" << endl;}
};template<class T>
class myClass {
public:T obj;//类模板中的成员函数void func1() {obj.showPerson1();}void func2() {obj.showPerson2();}
};void test01() {myClass<Person1> m;m.func1();//m.func2(); //报错,提示没有这个方法myClass<Person2> m2;m2.func2();
}int main() {test01();return 0;
}

(4)类模板对象做函数参数

** 类模板对象做函数参数** 学习目标:类模板实例化出的对象,向函数传参的方式** 三种方式:*      1.指定传入的类型:直接显示对象的数据类型*      2.参数模板化:将对象中的参数变为模板进行传递*      3.整个类模板化:将这个对象类型 模板化进行传递**/template<class T1, class T2>
class Person {
public:T1 name;T2 age;Person(T1 name, T2 age) {this->name = name;this->age = age;}void showPerson() {cout << "name=" << name << ";age=" << age << endl;}
};//1.指定传入类型
void printPerson1(Person<string, int> &p) {p.showPerson();
}void test01() {Person<string, int> p("孙悟空", 100);printPerson1(p);
}template<class T1, class T2>
void printPerson2(Person<T1, T2> &p) {p.showPerson();cout << "T1类型为:" << typeid(T1).name() << endl;cout << "T2类型为:" << typeid(T1).name() << endl;
}//2.参数模板花
void test02() {Person<string, int> p("猪八戒", 90);printPerson2(p);
}template<class T>
void printPerson3(T p) {p.showPerson();
}//3.整个类模板化
void test03() {Person<string, int> p("唐山", 20);printPerson3(p);
}int main() {cout << "test01()" << endl;test01();cout << "test02()" << endl;test02();cout << "test03()" << endl;test03();return 0;
}

(5)类模板与继承

/** 类模板与继承** 当类模板碰到继承时,需要注意:*      当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中的T的类型*      如果不指定,编译器无法给子类分配内存*      如果想灵活指定出父类中T的类型,子类也需要变为类模板**///类模板与继承
template<class T>
class Base {T m;
};//class Son:public Base{ //错误,必须要知道父类中的T类型,才能继承给子类
//
//};class Son : public Base<int> {};void test01() {Son son;
}//如果想灵活指定父类中T类型,子类也需要变类模板
template<class T1, class T2>
class Son2 : public Base<T2> {
public:T1 obj;Son2() {cout << "T1类型为:" << typeid(T1).name() << endl;cout << "T2类型为:" << typeid(T2).name() << endl;}
};void test02() {Son2<int, char> s2;
}int main() {test01();test02();return 0;
}

(6)类模板成员函数类外实现

/** 类模板成员函数类外实现* 学习目标:能够掌握类模板中的成员函数类外实现*/template<class T1,class T2>
class Person{
public:T1 name;T2 age;Person(T1 name,T2 age);void showPerson();
};//类模板 成员函数类外实现
template<class T1,class T2>
Person<T1,T2>::Person(T1 name,T2 age){this->name=name;this->age=age;
}
//成员函数的类外实现
template<class T1,class T2>
void Person<T1,T2>::showPerson(){cout<<"姓名:"<<name<<";年龄="<<age<<endl;
}void test01(){Person<string,int> p("AAA",18);p.showPerson();Person p2("AAA",18);p2.showPerson();
}int main() {test01();return 0;
}

(7)类模板与友元

/** 类模板与友元** 学习目标:*      掌握类模板配合友元函数的类内和类外实现*  全局函数类内实现 -- 直接在类内声明友元即可*  全局函数类外实现 -- 需要提前让编译器知道全局函数的存在*///让编译器提前知道Person类的存在
template<class T1, class T2>
class Person;//类外实现
//加空模板参数列表
//如果全局函数 是类外实现,需要让编译器提前知道这个函数的存在
template<class T1, class T2>
void printPerson2(Person<T1, T2> p) {cout << "类外实现:姓名:" << p.name << ";年龄:" << p.age << endl;
}//通过全局函数打印Perosn信息
template<class T1, class T2>
class Person {//全局函数 类内实现friend void printPerson(Person<T1, T2> p) {cout << "姓名:" << p.name << ";年龄:" << p.age << endl;}//全局函数 类外实现friend void printPerson2();public:T1 name;T2 age;Person(T1 name, T2 age) {this->name = name;this->age = age;}
};//1.全局函数类内实现
void test01() {Person p1("Tom", 18);printPerson(p1);
}//1.全局函数类外实现
void test02() {Person p2("Dog", 22);printPerson(p2);
}int main() {test01();test02();return 0;
}

(8)类模板案例

未学习
https://www.bilibili.com/video/BV1et411b73Z?p=183

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用navicate快速将Excel中的数据导入到数据库

表名称上右键&#xff0c;导入向导 这种方式速度还是很快的&#xff0c;18万条数据&#xff0c;3分钟左右就导入进去了。

Oracle集群管理-19C集群禁用numa和大页内存特性

Linux Redhat 7.9关闭内存管理特性 1 关闭大页内存 [rootdb1 ~]# cat /sys/kernel/mm/transparent_hugepage/defrag [always] madvise never [rootdb1 ~]# cat /sys/kernel/mm/transparent_hugepage/enabled [always] madvise never echo never > /sys/kernel/mm/transpare…

postgresql-多表连接

postgresql-多表连接 内连接查询左外连接查询右外连接查询全外连接查询交叉连接查询简写 总结 内连接查询 内连接用于返回两个表中匹配的数据行&#xff0c;使用关键字INNER JOIN表示&#xff0c;也可以简写成JOIN&#xff1b; selecte.first_name ,d.department_id fromcps…

Springboot整合shiro

导入依赖 <!-- 引入springboot的web项目的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> ​ <!-- shiro --><depende…

zookeeper 3.8.1安装和入门使用

1、zookeeper环境搭建&#xff08;Windows单机版&#xff09; 1.1、 前提 必须安装jdk 1.8&#xff0c;配置jdk环境变量&#xff0c;步骤略 1.2、安装zookeeper 地址&#xff1a;https://zookeeper.apache.org/ 1.2.1、选择releases版本 1.2.2、下载安装包并解压 1.2.3、配…

网络丢包问题,敢不敢这样定位?

下午好&#xff0c;我的网工朋友。 所谓丢包&#xff0c;是指在网络数据的收发过程中&#xff0c;由于种种原因&#xff0c;数据包还没传输到应用程序中&#xff0c;就被丢弃了。 这些被丢弃包的数量&#xff0c;除以总的传输包数&#xff0c;也就是我们常说的丢包率。 丢包…

3种轻量化框架总结

一般的卷积神经网络的参数量和计算量都很大&#xff0c;很难应用在资源有限的场景中。为了解决这个问题&#xff0c;通常是在训练好的模型上进行优化&#xff0c;如通过对模型压缩减少计算量和存储成本&#xff0c;也可以通过剪枝连接方法去掉了不重要的神经元连接或者通道修剪…

Python循环语句实战练习和循环嵌套详解

文章目录 循环语句while循环实战练习练习1&#xff1a;求100以内所有的奇数之和练习2&#xff1a;求100以内所有7的倍数之和&#xff0c;以及个数练习3&#xff1a;求1000以内所有的水仙花数练习4&#xff1a;获取用户输入的任意数&#xff0c;判断其是否是质数 循环嵌套练习1&…

无涯教程-JavaScript - BESSELY函数

描述 BESSELY函数针对x的指定顺序和值返回Bessel函数Yn(x)(也称为Weber函数或Neumann函数)。 语法 BESSELY(X, N)争论 Argument描述Required/OptionalXThe value at which to evaluate the function.RequiredNThe order of the function. If n is not an integer, it is tr…

Spring中Endpoint、HasFeatures、NamedFeature和Actuator的关系及实现原理

文章目录 1. 关系缘由2. Actuator简介及简单使用3. Endpoint和Actuator的关系4. Endpoint和HasFeatures的关系5. Endpoint和HasFeatures原理解析5.1 Endpoint的实现原理5.2 HasFeatures的实现原理 6. 个人闲谈 1. 关系缘由 我们经常可以在Springboot中看到Endpoint注解&#x…

什么牌子的led台灯质量好?热门的Led护眼台灯推荐

led台灯有环保无污染、耗能低、长寿命等优点&#xff0c;适合用在阅读、书写、批阅等办公或学习的场所。而挑选LED台灯时&#xff0c;分散光挡板做的比较好的优先选择&#xff0c;能分散大量蓝光&#xff0c;对眼睛危害较小。下面&#xff0c;小编为大家推荐五款质量好的led护眼…

EF框架基础应用入门

文章目录 一、介绍二、EF6框架基础1. 数据模型和实体类2. 数据库上下文&#xff08;DbContext&#xff09;介绍3. 配置数据模型与数据库表的映射关系 两种方式Fluent API和数据注解Fluent API数据注解 4. 数据库迁移&#xff08;Migration&#xff09;概述a. 创建初始迁移b. 更…

ElementUI浅尝辄止20:Pagination 分页

分页组件常见于管理系统的列表查询页面&#xff0c;数据量巨大时需要分页的操作。 当数据量过多时&#xff0c;使用分页分解数据。 1.如何使用&#xff1f; /*设置layout&#xff0c;表示需要显示的内容&#xff0c;用逗号分隔&#xff0c;布局元素会依次显示。prev表示上一页…

Vulnhub: Masashi: 1靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.236 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.236查看80端口的robots.txt提示三个文件 snmpwalk.txt内容&#xff0c;tftp服务在1337端口 sshfolder.txt内容&#xff0c…

日200亿次调用,喜马拉雅网关的架构设计

说在前面 在40岁老架构师 尼恩的读者社区(50)中&#xff0c;很多小伙伴拿到一线互联网企业如阿里、网易、有赞、希音、百度、滴滴的面试资格。 最近&#xff0c;尼恩指导一个小伙伴简历&#xff0c;写了一个《API网关项目》&#xff0c;此项目帮这个小伙拿到 字节/阿里/微博/…

管理类联考——数学——汇总篇——知识点突破——数据分析——计数原理——减法原理除法原理

减法原理 正面难则反着做(“ − - −”号) 【思路】当出现“至少、至多”、“否定用语"等正面较难分类的题目&#xff0c;可以采用反面进行求解&#xff0c;注意部分反面的技巧以及“且、或"的反面用法。 除法原理 看到相同&#xff0c;定序用除法消序( “ &quo…

python批量下载csdn文章

声明&#xff1a;该爬虫只可用于提高自己学习、工作效率&#xff0c;请勿用于非法用途&#xff0c;否则后果自负 功能概述&#xff1a; 根据待爬文章url(文章id)批量保存文章到本地&#xff1b;支持将文中图片下载到本地指定文件夹&#xff1b;多线程爬取&#xff1b; 1.爬取…

关于 Nginx 的哪些事

关于 Nginx 的哪些事 1、Nginx 主要功能2、Nginx 的常用命令2.1、启动Nginx2.2、停止 Nginx2.3、重新加载Nginx 配置2.4、检查Nginx配置文件2.5、指定配置文件2.6、检查Nginx版本2.7、显示Nginx帮助信息 3、Nginx 配置文件 nginx.conf3.1、Nginx 配置文件&#xff08;nginx.con…

NLP:生成熟悉NLP开源工具,如NLTK、 HanLP等,并搜寻、下载和熟悉PKU、 CoreNLP, LTP MSR, AS CITYI 等语料库。

目录 一、NLTK 二、HanLP 三、PKU 四、CoreNLP 五、LTP 六、MSR 一、NLTK NLTK&#xff08;Natural Language Toolkit&#xff09;是Python的一个开源自然语言处理库。它提供了大量已经预处理好的文本数据和语料库&#xff0c;以及一些常用的文本处理算法和NLP工具。例如&…

插入排序——希尔排序

1、简述&#xff1a; 希尔排序(Shells Sort)是插入排序的一种又称“缩小增量排序”&#xff08;Diminishing Increment Sort&#xff09;&#xff0c;是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。 希尔排…