期末速成C++【模板和STL和算法】
目录
1.模板
1.1模板的概念
1.2函数模板
1.3.类模板
2.STL的组成Standard Template Library
3.序列容器Sequence Container和迭代器
3.1vector
3.2迭代器的基本概念iterator
3.3迭代器的基本运算
3.4list
无效迭代器
4.仿函数
5.浅拷贝和深拷贝
6.算法
6.1 sort
6.2 erase
6.3 greater()
6.4 accumulate
6.5 copy
6.6 back_inserter
6.7 Lambda
6.8 generate_n
7.RTTI综合项目
1.模板
1.1模板的概念
- C++提供了模板机制,可以把类型参数化。带类型参数的函数称为函数模板,带类型参数的类称为类模板。
template<typename T>
T max( Ta,T b)
max<int>(100,200)
1.2函数模板
函数模板也可以重载
非模板函数优先于模板函数
1.3.类模板
2.STL的组成Standard Template Library
STL是大量的类模板和函数模板
访问容器中的元素,元素的位置(迭代器)
#include<algorithm>
vector
sort()对连续的容器进行快速排序的操作,只能数组只能vector。也是左闭右开区间。
assign()赋值:左闭右开区间赋值。vi.assign(arr,arr+3) vi.assign(begin,end)将首元素和end的前一个元素,即尾部元素。赋值到vector<int>vi容器里面
3.序列容器Sequence Container和迭代器
3.1vector
begin()是头元素;end()是最后一个元素的下一个位置。所以:*pre(vi.end())获取前一个元素
front() back()获取首尾元素的值。
Inset();erase()效率不高
Push_back();Pop_back()效率高(尾部)
3.2迭代器的基本概念iterator
指向数组的指针用法等同于迭代器
3.3迭代器的基本运算
sort是对连续的容器堆排序的函数。快排(数组)不能使用list,左闭右开区间
assign也是左闭右开区间。
3.4list
push_back push_front(头尾部操作)
无效迭代器
利用临时变量解决:
用这种解决!简便!
4.仿函数
- 仿函数的实质:对函数运算符重载()
仿函数:在类中重载“()”之后,这个类的对象可以像函数一样使用
Void operator()(const string str) //对()运算符重载函数
Void operator()(const float num) //对()运算符重载函数
仿函数在STL的算法中使用非常广泛。
Lambda表达式也是对仿函数的扩展。
5.浅拷贝和深拷贝
指针存在,导致调用两次拷贝构造函数(按位赋值)☞两个指针指向通过一块内存空间☞栈释放的时候,析构函数调用两次,第二次释放时候找不到释放的空间☞程序奔溃。
6.算法
generate_n(back_inserter(li), 10, []() {return rand() % 100;});
//使用generate_n函数和lambda表达式向list中添加10个随机数,每个随机数范围是0到99
// 使用copy函数和ostream_iterator将list中的元素复制到标准输出流,并且每个元素之间用空格分隔
copy(li.begin(), li.end(), ostream_iterator<int>(cout, " "));
6.1 sort
sort的第三个参数
1.内置仿函数greate<float>()
2.自定义仿函数-二元谓词
2.lambda表达式[](){}
6.2 erase
erase:删除容器中的元素
6.3 greater<float>()
std::greater<float>() 返回一个对象,该对象重载了 operator(),用于比较两个浮点数。
// 当你调用这个对象时(使用圆括号和参数),它会返回比较的结果。
//在比较两个浮点数时,应该使用“大于”比较而不是默认的“小于”比较。
// 因此,容器 vec 中的元素会按照降序进行排序
6.4 accumulate
6.5 copy
6.6 back_inserter
6.7 Lambda
6.8 generate_n
7.RTTI综合项目
Student.h
#pragma once
#include<iostream>
using namespace std;
class Student
{
public:
//构造函数-直接调用父类的构造函数
Student(string str);
//虚析构函数
virtual ~Student() {};
//都做都一样
void Study();
//纯虚函数-都要做方式不一样❗
virtual void PE() = 0;
protected:
string name;
};
//子类中的virtual可以省略
class Male:public Student
{
public:
//构造函数
Male(string str);
//虚析构函数
virtual ~Male() {};
//打篮球
virtual void PE();
//打游戏
void Game();
};
class Female :public Student
{
public:
//构造函数
Female(string str) :Student(str) {};
//虚析构函数
virtual ~Female() {};
//打排球
virtual void PE();
//购物
void Shopping();
};
Student.cpp
#include "Student.h"
Student::Student(string str):name(str)
{
}
void Student::Study()
{
cout << "我爱学习" << endl;
}
Male::Male(string str) :Student(str)
{
}
void Male::PE()
{
cout << "篮球小天才" << endl;
}
void Male::Game()
{
cout << "打游戏" << endl;
}
void Female::PE()
{
cout << "打排球" << endl;
}
void Female::Shopping()
{
cout << "购物" << endl;
}
main.c
//综合项目
//往容器中写入类,需要new
ifstream& operator>>(ifstream& file, list<Student*>& l)
{
string type,name;
file >> type >> name;
if (type == "男生")
{
l.push_back(new Male(name));
}
if (type == "女生")
{
l.push_back(new Female(name));
}
return file;
}
int main()
{
list<Student*> li;//定义容器li对象
ifstream ifs;//定义一个输入文件流的对象
ifs.open("in.txt", ios::in);//打开in.txt用读取的方式
//判断是否打开失败
if (!ifs)
{
cout << "文件打开失败!" << endl;
exit(0);
}
//开始将文件内容写入容器
while (!ifs.eof())//eof是end of 是否在末尾
{
ifs >> li;//循环写入容器
}
//关闭文件
ifs.close();
//基于范围for循环,打印在屏幕上输出
for (Student* p : li)
{
//1.公共的
p->Study();
//2.都有但是行为不同
p->PE();
//3.访问各自特有的
//RTTI运行时类型识别
if (typeid(*p) == typeid(Male))
{
//父类指针转换成子类指针,向下转换
Male* pt = dynamic_cast<Male*>(p);
pt->Game();
}
else//(typeid(*p) == typeid(Female))
{
Female* ps = dynamic_cast<Female*>(p);
ps->Shopping();
}
}
//程序释放
for (Student* p : li)
{
delete p;
}
}