C++基础 抽象类 类模板 STL库 QT环境

一、抽象类

1、纯虚函数

        在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数。

        语法:

virtual 返回值类型 函数名 (参数列表) = 0;

2. 抽象类

1) 概念

        有纯虚函数所在的类,称为抽象类。

2) 特点

        抽象类不能直接定义对象。

        抽象类派生子类,子类必须实现所有的纯虚函数,否则子类也是一个抽象类。

        抽象类可以定义指针。


示例代码:

#include <iostream>
#define PI 3.14159
using namespace std;class Shap{ // 抽象类
public:virtual double cal_s() = 0; // 纯虚函数virtual double cal_c() = 0;virtual void display() = 0;
};class Square : public Shap{
private:int longa;int shorta;
public:Square(int a,int b):longa(a),shorta(b){};void display(){cout<<"Square:";}double cal_s(){return longa * shorta ;}double cal_c(){return 2 * (longa + shorta);}
};
class Circle : public Shap{
private:int r;
public:Circle(int r):r(r){};void display(){cout<<"Circle:";}double cal_s(){return PI * r * r;}double cal_c(){return 2 * PI * r ;}
};
class Single : public Shap{
private:int a;int b;int c;
public:Single(int a,int b,int c):a(a),b(b),c(c){};void display(){cout<<"Single:";}double cal_s(){return(b * a * c) ;}double cal_c(){return a + b+  c;}
};
void cal_s(Shap *p){p->display();cout<<"S = "<<p->cal_s()<<endl;
}
void cal_c(Shap *p){p->display();cout<<"C = "<<p->cal_c()<<endl;
}int main(){Square a(2,3);Single b(1,3,3);Circle c(3);cal_c(&a);cal_s(&a);cal_c(&b);cal_s(&b);cal_c(&c);cal_s(&c);return 0;
}

输出:


二、类模板

1. 概念

        实现一个通用类,类中所需的类型使用虚拟类型表示。一般通过类模板实现不同的数据结构,实现数据类型与数据结构的分离。同一个数据结构可以存储不同类型的数据。

2. 语法

Template <class/typename T>Class  类名{ ...  ...  };

3. 使用类模板定义对象

        必须显示指定类型。

        类名 <指定类型>  对象名;

        C++编译器会根据指定类型将类模板生成具体的类,然后再使用。

4. 类模板中的继承

        派生普通类,必须指定具体类型派生

 Class 派生类名: public 类模板<指定类型> {  ... ...  };

5. 类模板中的static成员

        从类模板实例化的每个模板类都有自己的静态成员,同一个模板类的对象共享一个静态成员。


三、STL库

1. 理论

        STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。现然主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间。

        STL的从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),容器和算法通过迭代器可以进行无缝地连接。几乎所有的代码都采 用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。

        在C++标准中,STL被组织为下面的13个头文 件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack> <utility>

Class 派生类名: public 类模板<指定类型> {  ... ...  };

STL详细的说六大组件

  • 容器(Container)
  • 算法(Algorithm)
  • 迭代器(Iterator)
  • 仿函数(Function object)
  • 适配器(Adaptor)
  • 空间配制器(allocator)

使用STL的好处

(1)STL是C++的一部分,因此不用额外安装什么,它被内建在你的编译器之内。

2STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但是这种分离确实使得STL变得非常通用。例如,在STL的vector容器中,可以放入元素、基础数据类型变量、元素的地址;STL的sort()函数可以用来操作vector,list等容器。

        1) 程序员可以不用思考STL具体的实现过程,只要能够熟练使用STL就OK了。这样他们就可以把精力放在程序开发的别的方面。

        2) STL具有高可重用性,高性能,高移植性,跨平台的优点。

        高可重用性:STL中几乎所有的代码都采用了模板类和模版函数的方式实现,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。关于模板的知识,已经给大家介绍了。

        高性能:如map可以高效地从十万条记录里面查找出指定的记录,因为map是采用红黑树的变体实现的。(红黑树是平横二叉树的一种)

        高移植性:如在项目A上用STL编写的模块,可以直接移植到项目B上。

        跨平台:如用windows的Visual Studio编写的代码可以在Mac OS的XCode上直接编译。

        1) 程序员可以不用思考STL具体的实现过程,只要能够熟练使用STL就OK了。这样他们就可以把精力放在程序开发的别的方面。

        2) 了解到STL的这些好处,我们知道STL无疑是最值得C++程序员骄傲的一部分。每一个C++程序员都应该好好学习STL。只有能够熟练使用STL的程序员,才是好的C++程序员。

        3) 总之:招聘工作中,经常遇到C++程序员对STL不是非常了解。大多是有一个大致的映像,而对于在什么情况下应该使用哪个容器和算法都感到比较茫然。STLC++程序员的一项不可或缺的基本技能,掌握它对提升C++编程大有裨益。


2. 容器

        (1) 作用:    

        用来管理一组数据

        (2) 分类:
        1) 序列式容器(Sequence containers)

        序列式容器是一种数据结构,它以线性序列的方式来存储某一特定类型的数据。这类容器并不会自动对存储的元素按照值的大小进行排序,而是保持元素的存储顺序与其在容器中的顺序一致。

        2) 关联式容器(Associated containers)

        关联式容器是一种数据结构,它支持高效的关键字查找和访问。关联式容器依照特定的排序准则自动为元素排序。


3. Vector

1) vector容器简介

        vector是将元素置于一个动态数组中加以管理的容器,是通过类模板实现。

        vector可以随机存取元素(支持索引值直接存取, 用[]操作符或at()方法)。

        vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比较费时

        包含头文件: #include <vector>

2) vector与普通数组的区别

        普通数组是静态空间,vector可以动态拓展。

        动态拓展:并不是在原空间之后接新的空间,而是找更大的内存空间,然后将

原数据拷贝到新空间,释放原空间。

3) 创建对象

        vector<T> vecT;  // 采用类模板实现,默认构造函数

        vector(beg,end);  // 构造函数将[beg, end)区间中的元素拷贝给本身。注意该区间是左闭右开的区间。

        vector(n,elem);   // 构造函数将n个elem拷贝给本身。

        vector(const vector &vec);  // 拷贝构造函数

4) 插入数据

        insert(pos,elem); //在pos位置插入一个elem元素的拷贝

        insert(pos,n,elem);   //在pos位置插入n个elem数据,无返回值。

        insert(pos,beg,end);   //在pos位置插入[beg,end)区间的数据,无返回值

5) 遍历

        at(int  index);//返回下标index所在的元素

        operator[];//返回下标index所在的元素

        迭代器的方式遍历;//迭代器支持随机操作

6) 属性操作

        size(); //获取容器大小

        resize(); //设置容器大小

        empty();//判断容器是否为空

7) 数据的存取

        back(); // 返回最后一个元素

        front(); // 返回第一个元素

        push_back(); // 尾部追加

        pop_back(); // 尾部删除

8) 删除操作

        clear();     //移除容器的所有数据

        erase(beg,end);  //删除[beg,end)区间的数据,返回下一个数据的位置

        erase(pos);    //删除pos位置的数据,返回下一个数据的位置


示例代码:

#include <iostream>
#include <vector>
using namespace std;int main(){vector<int> v;vector<int>::iterator it;v.push_back(1); // 尾端插入元素v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);// 插入it =  v.begin();v.insert(it + 2,9);// 遍历for(int i = 0;i<v.size();i++)cout<<v[i]<<" ";cout<<endl;// 删除最后一个元素v.pop_back();// at遍历for(int i = 0;i<v.size();i++)cout<<v.at(i)<<" ";cout<<endl;// 删除(左闭右开)v.erase(it,it + 2);// 迭代器遍历for(vector<int>::iterator it =  v.begin();it != v.end();it++)cout<<*it<<" ";cout<<endl;// 删除it = v.begin();v.erase(it + 1);// 迭代器逆向遍历cout<<"迭代器逆向遍历"<<endl;for(vector<int>::reverse_iterator it =  v.rbegin();it != v.rend();it++)cout<<*it<<" ";cout<<endl;// 清空v.clear();if(v.empty()) cout<<"is empty"<<endl;else cout<<"is not empty"<<endl;return 0;
}

输出:


4. Deque

1) deque简介

        deque是双端数组,也是通过类模板实现,deque头部和尾部添加或移除元素都非常快速。但是在中部安插元素或移除元素比较费时。

        包含头文件:#include <deque>

2) 创建对象

        deque<T> deqT;

        deque(beg,end);    //构造函数将[beg, end)区间中的元素拷贝给本身。注意该区间是左闭右开的区间。

        deque(n,elem);   //构造函数将n个elem拷贝给本身。

        deque(const deque  &deq);  //拷贝构造函数。

3) 插入数据

        deque.insert(pos,elem);   // 在pos位置插入一个elem元素的拷贝,返回新数据的位置。

        deque.insert(pos,n,elem);   // 在pos位置插入n个elem数据,无返回值。

        deque.insert(pos,beg,end);   // 在pos位置插入[beg,end)区间的数据,无返回值。

4) 遍历

        at(int  index); //返回下标index所在的元素

        operator[]; //返回下标index所在的元素

        迭代器的方式遍历;//迭代器支持随机操作

5) 属性操作

        size(); //获取容器大小

        resize(); //设置容器大小

        empty(); //判断容器是否为空

6) 数据的存取

        back(); //返回最后一个元素

        front(); //返回第一个元素

        push_back(); //尾部追加

        pop_back(); //尾部删除

        push_front(); //头部插入

        pop_front(); //头部删除

7) 删除

        clear();     //移除容器的所有数据

        erase(beg,end);  //删除[beg,end)区间的数据,返回下一个数据的位置

        erase(pos);    //删除pos位置的数据,返回下一个数据的位置

示例代码:

#include <iostream>
#include <deque>using namespace std;// 输出
void display(deque<int> d){deque<int>::iterator it;cout<<"deque :";for(it = d.begin();it != d.end();it++)cout<<*it<<" ";cout<<endl;
}int main(){deque<int>d;deque<int>::iterator it;d.push_back(1); // 尾部追加d.push_back(2);d.push_back(3);d.push_front(-1); // 头部追加d.push_front(-2);d.push_front(-3);display(d);cout<<"第一个元素:"<<d.front()<<endl;cout<<"最后一个元素:"<<d.back()<<endl;cout<<"删除尾端元素"<<endl;d.pop_back(); // 删除尾端元素display(d);cout<<"删除头端元素"<<endl;d.pop_front(); // 删除头端元素display(d);cout<<"在第2个位置插入3个9"<<endl;it = d.begin();d.insert(it + 1,3,9); // 插入display(d);return 0;
}

输出:


5. List

1) list简介

        list是一个双向链表容器,可高效地进行插入删除元素,通过类模板实现。

        list不可以随机存取元素,所以不支持 at.(pos) 函数与[]操作符。it++(ok) it+5(err)

        包含头文件:#include <list>

2) 创建对象

        list<T> lstT; // 默认构造函数

        list(beg,end); // 构造函数将[beg, end)区间中的元素拷贝给本身。注意该区间是左闭右开的区间

        list(n,elem);   // 构造函数将n个elem拷贝给本身

        list(const list &lst);  // 拷贝构造函数

3) 插入数据

        list.insert(pos,elem);   // 在pos位置插入一个elem元素的拷贝

        list.insert(pos,n,elem);   // 在pos位置插入n个elem数据,无返回值

        list.insert(pos,beg,end);   // 在pos位置插入[beg,end)区间的数据,无返回值

4) 遍历

        通过迭代器遍历。迭代器只能进行自增操作,不支持it+n的操作。

5) 属性操作

     size(); // 获取容器大小

     resize(); // 设置容器大小

     empty(); // 判断容器是否为空

6) 数据的存取

      back(); // 获取尾部元素

      front(); // 获取头部元素

      push_back(); // 尾部追加

      push_front(); // 头部追加

      pop_back(); // 尾部删除

      pop_front(); // 头部删除

7) 删除

        list.clear();        //移除容器的所有数据

        list.erase(beg,end);  //删除[beg,end)区间的数据,返回下一个数据的位置

        list.erase(pos);    //删除pos位置的数据,返回下一个数据的位置

        list.remove(elem);   //删除容器中所有与elem值匹配的元素

8) 排序

        List.sort() ;   //默认按照升序排序

        List.sort(com); // 将比较规则的入口地址传过来,可以实现升序或者降序,也可以对自定义的数据类型进行排序

示例代码:

#include <iostream>
#include <list>
using namespace std;// 输出
void display(list<int> l){list<int>::iterator it;cout<<"list :";for(it = l.begin();it != l.end();it++)cout<<*it<<" ";cout<<endl;
}// 比较规则
bool Compare(int &x,int &y){return x > y ? true : false;
}int main(){list<int> l;list<int>::iterator it;l.push_back(1);l.push_back(3);l.push_back(2);l.push_front(-2);l.push_front(-1);l.push_front(-3);display(l);cout<<"第一个元素: "<<l.front()<<endl;cout<<"最后一个元素: "<<l.back()<<endl;cout<<"删除尾端元素"<<endl;l.pop_back(); // 删除尾端元素display(l);cout<<"删除头端元素"<<endl;l.pop_front(); // 删除头端元素display(l);cout<<"在第2个位置插入2个9"<<endl;it = l.begin();it++;l.insert(it,2,9); // 插入元素// it执行完上述代码后指向第4个元素display(l);cout<<"删除第3个元素"<<endl;l.erase(--it); // 删除第3个元素display(l);cout<<"默认升序排序"<<endl;l.sort();display(l);cout<<"降序排序"<<endl;//l.sort(Compare); // 通过函数指针传入比较规则l.sort();l.reverse(); // 先升序排序,然后再翻转display(l);return 0;
}

输出:

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

c语言选择排序

选择排序思想&#xff1a; 反复地从未排序部分选择最小&#xff08;或最大&#xff09;的元素&#xff0c;将其放到已排序部分的末尾&#xff1b; 首先用一个变量min来保存数组第一个元素的下标&#xff0c;然后用这个下标访问这个元素&#xff0c;将这个元素与它后面的元素相…

数字后端教程之Innovus report_property和get_property使用方法及应用案例

数字IC后端实现Innovus中使用report_property可以报告出各种各样object的属性&#xff0c;主要有cell&#xff0c;net&#xff0c;PG Net&#xff0c;Pin&#xff0c;时钟clock&#xff0c;时序库lib属性&#xff0c;Design属性&#xff0c;timing path&#xff0c;timin arc等…

Golang | Leetcode Golang题解之第560题和为K的子数组

题目&#xff1a; 题解&#xff1a; func subarraySum(nums []int, k int) int {count, pre : 0, 0m : map[int]int{}m[0] 1for i : 0; i < len(nums); i {pre nums[i]if _, ok : m[pre - k]; ok {count m[pre - k]}m[pre] 1}return count }

OpenCompass 评测 InternLM-1.8B 实践

1. API评测 首先我们创建模型的配置文件&#xff0c;我们需要定义评测模型的类型&#xff0c;是OpenAISDK类型&#xff0c;然后是模型名称&#xff0c;请求地址和API等等内容。然后我们通过命令行python run.py --models puyu_api.py --datasets demo_cmmlu_chat_gen.py --deb…

【算法】——二分查找合集

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 零&#xff1a;二分查找工具 1&#xff1a;最基础模版 2&#xff1a;mid落点问题 一&#xff1a;最…

Python 的 Pygame 库,编写简单的 Flappy Bird 游戏

Pygame 是一个用 Python 编写的开源游戏开发框架&#xff0c;专门用于编写 2D 游戏。它提供了丰富的工具和功能&#xff0c;使得开发者能够快速实现游戏中的图形渲染、声音播放、输入处理和动画效果等功能。Pygame 非常适合初学者和想要快速创建游戏原型的开发者。 Pygame 的主…

Ubuntu上搭建Flink Standalone集群

Ubuntu上搭建Flink Standalone集群 本文部分内容转自如下链接。 环境说明 ubuntu 22.06 先执行apt-get update更新环境 第1步 安装JDK 通过apt自动拉取 openjdk8 apt-get install openjdk-8-jdk执行java -version&#xff0c;如果能显示Java版本号&#xff0c;表示安装并…

【stablediffusion】ComfyUI | 恐怖如斯的放大模型DifFBIR,超分辨率放大、人脸修复、图像去噪 | 效果炸裂 | 强烈推荐

今天&#xff0c;我们将向您介绍一款令人兴奋的更新——Stable Diffusion的ComfyUI放大模型DifFBIR。这是一款基于Stable Diffusion技术的AI绘画工具&#xff0c;旨在为您提供一键式图像放大的便捷体验。无论您是AI绘画的新手还是专业人士&#xff0c;这个工具都能为您带来极大…

PCB设计基础

系列文章目录 文章目录 系列文章目录前言一、PCB设计术语与定义二、焊盘堆和过孔的构成及分类总结 前言 介绍PCB的基础内容。 一、PCB设计术语与定义 PCB全称为Printed Circuit Board&#xff0c;印刷电路板。它是电子元器件的支撑体&#xff0c;是重要的电子部件以及电气连接…

Node.js下载安装及环境配置教程

一、进入官网地址下载安装包 Node.js 中文网 选择对应你系统的Node.js版本&#xff0c;这里我选择的是Windows系统、64位 二、安装程序 &#xff08;1&#xff09;下载完成后&#xff0c;双击安装包&#xff0c;开始安装Node.js (2)直接点【Next】按钮&#xff0c;此处可根据…

深度学习知识点3-CBAM轻量的注意力模块

论文&#xff1a;&#xff08;2018&#xff09;包含空间注意力和通道注意力两部分1807.06521https://arxiv.org/pdf/1807.06521 通道注意力&#xff1a;对input feature maps每个feature map做全局平均池化和全局最大池化&#xff0c;得到两个1d向量&#xff0c;再经过conv&…

《云原生安全攻防》-- K8s安全防护思路

从本节课程开始&#xff0c;我们将正式进入防护篇。通过深入理解K8s提供的多种安全机制&#xff0c;从防守者的角度&#xff0c;运用K8s的安全最佳实践来保障K8s集群的安全。 在这个课程中&#xff0c;我们将学习以下内容&#xff1a; K8s安全防护思路&#xff1a;掌握K8s自身提…

MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并

MySQL技巧之跨服务器数据查询&#xff1a;基础篇-A数据库与B数据库查询合并 上一篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MySQL数据库的链接名: MY_ODBC_MYSQL 以…

基于物联网的智能超市快速结算系统

摘 要 当今社会的商品层出不穷&#xff0c;人们因为越来越多大型仓储超市的出现使得生活更加便利&#xff0c;但许多随之而来的新问题也给人们带来了许多的不便&#xff0c;例如商家一直被更换标签不及时、货物丢失、超市内物品更换处理不及时、超市内人流高峰期人流控制不得…

JavaScript面向对象笔记(4)

一、正则表达式 1.正则表达式概述 Regular Expression&#xff1a;是用于匹配字符串组合的模式&#xff0c;再javaScript中&#xff0c;正则表达式也是对象。 正则表达式通常被用来检索、替换某个模式&#xff08;规则&#xff09;的文本。例如&#xff1a;表单校验&#xf…

20241112-Pycharm使用托管的Anaconda的Jupyter Notebook

Pycharm使用托管的Anaconda的Jupyter Notebook 要求 不要每次使用 Pycharm 运行 Jupyter 文件时都要手动打开 Anaconda 的 Jupyter Notebook 正文 pycharm中配置好会自动安装的&#xff0c;有的要自己配置 Pycharm中配置 文件 ——> 设置 ——> 语言和框架……&am…

vscode - 设置 Python 版本

在使用 vscode 编码 Python 时&#xff0c;选择合适的 Python 版本。 解决方法 使用快捷键 CtrlShiftP 打开命令窗口: 选择 “Python: Select Interpreter”&#xff0c;弹窗显示现有的 Python 版本: 回车选择需要的Python 版本即可。

【量化交易笔记】14.模拟盘效果

说明 距离上一篇的量化文章有一段时间&#xff0c;应小伙伴要求&#xff0c;继续写下去&#xff0c;我思考了一下&#xff0c;内容有很多&#xff0c;绝大多数是研究的过程&#xff0c;并且走的是弯路&#xff0c;分享了怕影响大伙&#xff0c;之前因为行情不好&#xff0c;研…

git rebase --continue解冲突操作

git rebase --continue解冲突操作 如果只是执行了 git rebase 命令&#xff0c;那么git会输出一下“错误”提示&#xff1a; There is no tracking information for the current branch. Please specify which branch you want to rebase against. See git-rebase(1) for detai…

nodejs express 框架使用

1. 准备环境 Nodejs 版本 v18.12.1, yarn 版本 1.22.21 2. 初始化项目 创建项目目录 express_demo01&#xff0c;进入目录&#xff0c;执行命令 npm init -y 生成 package.json 文件 圈起来的那一行修改为上图所示。使用 npm run dev 即可启动项目。 安装express 和 body-p…