0
点赞
收藏
分享

微信扫一扫

重生之——c++与我不得不说的一些事

洛茄 2022-02-20 阅读 67

看这里!!!本文顺序按照黑马视频所写,不仅对视频内容重点进行了分析,并且包含了黑马视频课程所有代码,代码链接已经贴在了下方(工程文件可直接运行),如果你觉得有帮助的话,可以动动发财小手,帮我点个赞哦!部分文件截图如下:

链接:https://pan.baidu.com/s/14thaue7oG1f4s5PVOmQwTQ 
提取码:p1cv


目录

1丶指针

2丶内存分区模型

3丶引用

4丶函数

5丶类和对象

6丶继承

7丶多态

8丶文件操作

9丶模板

10丶STL-常用容器

11丶STL-函数对象

12丶STL-常用算法

附录丶算法

1.1 const

1.1.1常量指针

1.1.2指针常量

1.1.3修饰指针+常量

2.1程序运行前

2.1.1全局区

2.1.2代码区

 2.2程序运行后

2.2.1栈区

 2.2.2堆区

2.3new操作符

2.3.1new的语法

3.1引用的基本使用

3.2引用的注意事项

3.3引用做函数参数

3.4引用做函数返回值

3.5引用的本质

3.6常量引用

4.1函数默认参数

4.2函数占位参数

4.3函数重载

4.3.1函数重载概述

4.3.2函数重载注意事项

5类和对象

5.1封装

5.1.1封装的语法

5.1.2封装的权限控制

5.1.3 struct 和 calss 区别

5.1.4 成员属性设置为私有化

5.2对象的初始化和清理

5.2.1构造函数和析构函数语法

5.2.2构造函数的分类及调用

5.2.3拷贝构造函数调用

5.2.4构造函数调用规则

5.2.5深拷贝和浅拷贝

5.2.6初始化列表

5.2.7类对象作为类成员

5.2.8静态成员变量

5.2.9静态成员函数

5.3c++对象模型和this指针

5.3.1成员变量和成员函数分开存储

5.3.2this指针

5.3.3空指针调用成员函数

5.3.4const修饰成员函数

5.4友元

5.4.1全局函数做友元

5.4.2类做友元

5.4.3成员函数做友元

5.5运算符重载

5.5.1加号运算符重载

5.5.2左移运算符重载

5.5.3递增递减运算符重载

5.5.4赋值运算符重载

5.5.5关系运算符重载

5.5.6函数调用运算符重载

6继承

6.1继承的基本语法

6.2继承方式

6.3继承中的对象模型

6.4继承中构造和析构顺序

6.5继承同名成员处理方式

6.6.继承同名静态成员处理方式

6.7多继承语法

6.8菱形继承

7多态

7.1多态的基本使用

7.2多态使用的原理

​7.3纯虚函数和抽象类

7.4虚析构和纯虚析构

8文件操作

8.1文本文件

8.1.1写文件

8.1.2读文件

8.2二进制文件

8.2.1写文件

8.2.2读文件

9模板

9.1模板的概念

9.2函数模板

9.2.1函数模板语法

9.2.2函数模板注意事项

9.2.3普通函数和函数模板区别

9.2.4普通函数和函数模板的调用规则

9.2.5模板的局限性

9.3类模板

9.3.1类模板语法

9.3.2类模板于函数模板区别

9.3.3类模板中成员函数创建时机

9.3.4类模板对象做函数参数

9.3.5类模板与继承

9.3.6类模板成员函数类外实现

9.3.7类模板分文件编写

9.3.8类模板与友元

10STL-常用容器

10.1STL初始

10.1.1STL的诞生

10.1.2STL基本概念

10.1.3STL六大组件

10.2STL中容器,算法,迭代器

10.2.1STL中容器,算法,迭代器概念

10.2.2vector存放内置数据类型

10.2.3vector存放自定义数据类型

10.2.4vector容器嵌套容器

10.3string容器

10.3.1string容器基本概念

10.3.2string构造函数

10.3.3string赋值操作

10.3.4string字符串拼接

10.3.5string查找和替换

10.3.6string字符串比较

10.3.7string字符读写

10.3.8string插入和删除

10.3.9string子串

10.4vector容器

10.4.1vector基本概念

10.4.2vector构造函数

10.4.3vector赋值操作

10.4.4vector容量和大小

10.4.5vector插入和删除

10.4.6vector数据读写

10.4.7vector互换容器

10.4.8vector预留空间

10.5deque容器

10.5.1deque容器基本概念

10.5.2deque构造函数

10.5.3deque赋值操作

10.5.4deque大小操作

10.5.5deque插入和和删除

10.5.6deque数据读写

10.5.7deque排序

10.6stack容器

10.6.1stack基本概念

10.6.2stack常用接口

10.7queue容器

10.7.1queue基本概念

10.7.2queue常用接口

10.8list容器

10.8.1list基本概念

10.8.2list构造函数

10.8.3list赋值和操作

10.8.4list大小操作

10.8.5list插入和删除

10.8.6list数据存取

10.8.7list反转和排序

10.9set和multiset容器

10.9.1set基本概念

10.9.2set构造和赋值

10.9.3set大小和交换

10.9.4set插入和删除

10.9.5查找和统计

10.9.6set和multiset区别

10.9.7pair队组创建

10.9.8set容器内置数据排序

10.9.9set容器自定义数据排序

10.10map和multimap容器

10.10.1map基本概念

10.10.2map构造和赋值

10.10.3map大小和交换

10.10.4map插入和删除

10.10.5map查找和统计

10.10.6map容器内置数据排序

11.1STL-函数对象

11.1.1函数对象基本概念

11.1.2函数对象使用

11.2谓词

11.2.1谓词概念

11.2.2一元谓词

11.2.3二元谓词

11.3内建函数对象

11.3.1内建函数对象意义

11.3.2算术仿函数

11.3.3关系仿函数

11.3.4逻辑仿函数

12STL常用算法

12.1常用算法基本概念

12.2常用遍历算法

12.2.1for_each

12.2.2transform

12.3常用查找算法

12.3.1find

12.3.2find_if

12.3.3adjacent_find

12.3.4binary_search

12.3.5count

12.3.6count_if

12.4常用排序算法

12.4.1sort

12.4.2random_shuffle

12.4.3merge

12.4.5reverse

12.5常用拷贝和替换算法

12.5.1copy

12.5.2replace

12.5.3replace_if

12.5.4swap

12.6常用算术生成算法

12.6.1accumulate

12.6.2fill

12.7常用集合算法

12.7.1set_intersection

12.7.2set_unin

12.7.3set_difference

1丶冒泡排序

2丶选择排序


1丶指针

2丶内存分区模型

3丶引用

4丶函数

5丶类和对象

6丶继承

7丶多态

8丶文件操作

9丶模板

10丶STL-常用容器

11丶STL-函数对象

12丶STL-常用算法

附录丶算法


1.1 const

1.1.1常量指针

	int a = 10, b = 20;
	const int* p1;//定义
	//*p1 = 10;错误
	p1 = &b;

1.1.2指针常量

	int c = 10, d = 20;
	int* const p2 = &c;//定义
	*p2 = 30;
	//p2=&d 错误

1.1.3修饰指针+常量

	int e = 10, f = 20;
	const int * const p3= &e;
	//*p3 = 10;错误
	//p3=&f 错误

2.1程序运行前

2.1.1全局区

2.1.2代码区

 2.2程序运行后

2.2.1栈区

 2.2.2堆区

 把一个整型数据10放到堆区,然后把这个10的地址用栈区的指针来保存,并且堆区的这个整型数据10是是否存在取决于程序员。

2.3new操作符

2.3.1new的语法

//单个数据:
int* p = new int(10);     
delete p;
//一个数组:
int* p = new int(10);     
delete[] arr;

3.1引用的基本使用

3.2引用的注意事项

3.3引用做函数参数

void swap3(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}

3.4引用做函数返回值

	int &ref = test2();
	cout << ref << endl;
	test2() = 100;//本质是令a=100
	cout << ref << endl;

3.5引用的本质

int& ref = a;
//自动转换为 int *const ref = &a 指针常量是指针指向不能变,也就是引用不能变
func(a)
void func(int& ref)
//转为 int *const ref=&a;
{
	ref = 100;//ref是引用,转为 *ref=100
}

3.6常量引用

void showValue(const int &val)
{
	//val = 100;//不能修改 val 的值
	cout << val << endl;
}

4.1函数默认参数

 func(10,20)
int func(int a,int b=10,int c=30)
{
	return a + b + c;
}

4.2函数占位参数

func(20,10);
void func(int a,int)
{
	cout << "这是函数调用" << endl;
}

4.3函数重载

4.3.1函数重载概述

void func()
void func(int a)
void func(double a)
void func(int a,double b)
void func(double a, int b)

4.3.2函数重载注意事项

//引用作为函数重载条件
int a = 10;
func(a);
const int b = 20;
func(b);
void func(int &a)
{
	cout << "这是func1调用" << endl;
}

void func(const int& a)
{
	cout << "这是func2调用" << endl;
}
//函数重载遇到函数默认参数
func(10)//错误
func(10,20)//正确
void func(int a,int b=10)
{
	cout << "这是func3调用" << endl;
}
void func(int a)
{
	cout << "这是func4调用" << endl;
}

5类和对象

5.1封装

5.1.1封装的语法

//代表设计一个类,后面接名字
class Circle
{
	//访问权限:公告权限
public:
	//属性:半径
	int m_r;
	//行为:获取圆的周长
	double caclcuateZC()
	{
		return 2 * PI * m_r;
	}
};
	//通过圆类创建具体(圆)对象
	Circle c1;
	//给圆对象的属性进行赋值
	c1.m_r = 10;
	cout << "圆的周长:" << c1.caclcuateZC() << endl;

5.1.2封装的权限控制

class Person
{
public:
	string m_name;
protected:
	string m_car;
private:
	int m_password;
public:
	void func()
	{
		m_name = "张三";
		m_car = "拖拉机";
		m_password = 123456;
	}
};

5.1.3 struct 和 calss 区别

5.1.4 成员属性设置为私有化

class Person
{
public://在类里面设置一个公告接口,来设置调用私有属性的值
	//写姓名
	void setName(string name)
	{
		m_name = name;
	}
	//读姓名
	string getName()
	{
		return m_name;
	}
private://在类里面设置属性为私有
	string m_name;//可读可写
};

5.2对象的初始化和清理

5.2.1构造函数和析构函数语法

class Person
{
public:
	//1,构造函数
	Person()
	{
		cout << "Person构造函数的调用" << endl;
	}
	//2,析构函数
	~Person()
	{
		cout << "Person析构函数的调用" << endl;
	}
};

5.2.2构造函数的分类及调用

class Person
{

public:
	//1,构造函数无参
	Person()
	{
		cout << "Person无参构造函数的调用" << endl;
	}
	//1,构造函数有参
	Person(int a)
	{
		m_age = a;
		cout << "Person有参构造函数的调用" << endl;
	}
	//拷贝构造
	Person(const Person &p)
	{
		m_age = p.m_age;
		cout << "Person拷贝构造函数的调用" << endl;
	}

	//2,析构函数
	~Person()
	{
		cout << "Person析构函数的调用" << endl;
	}
	int m_age;
};
	//括号法
	Person p;//无参 默认方式
	Person p2(10);//有参
	Person p3(p2);//拷贝
	//显示法
	Person p1;//无参
	Person p2 = Person(10);//有参
	Person p3 = Person(p2);//拷贝
	//隐式转换法
	Person p4 = 10;//相当于写了 Person p4 = Person(10)
	Person p5 = p4;

5.2.3拷贝构造函数调用

void test1()
{
	Person p1(20);
	Person p2(p1);
	cout << "pw的年龄:" << p2.m_age << endl;
}
void doWork(Person p)
{
	
}
void test2()
{
	Person p;
	doWork(p);
}
Person doWork2()
{
	Person p3;
	return p3;
}

void test3()
{
	Person p = doWork2();

}

5.2.4构造函数调用规则

5.2.5深拷贝和浅拷贝

	//深拷贝
	Person(const Person& p)
	{
		cout << "Person拷贝构造函数的调用" << endl;
		m_age = p.m_age;
		//m_height = p.m_height;编译器默认实现
		m_height = new int(*p.m_height);//重新开辟一个堆区空间存放

	}
	~Person()
	{
		//将堆区数据进行释放
		if (m_height != NULL)
		{
			delete m_height;
			m_height = NULL;

		}
		cout << "Person析构函数的调用" << endl;
	}

5.2.6初始化列表

class Person
{
public:
	//初始化列表操作
	Person(int a,int b,int c) :m_a(a), m_b(b), m_c(c)
	{
		
	}
	int m_a;
	int m_b;
	int m_c;
};
void test2()
{
	Person p1(10, 200, 30);
}

5.2.7类对象作为类成员

5.2.8静态成员变量

class Person
{
public:
	static int m_A;//所有对象共享这份数据,编译阶段分配内存,类内声明类外初始化
	//访问权限
private:
	static int m_B;
};
int Person::m_A=100;
int Person::m_B = 300;
void test2()
{
	//通过对象访问
	Person p;
	cout << p.m_A << endl;
	//通过类名访问
	cout << Person::m_A << endl;
	//cout << Person::m_B << endl;因为B是私有,所以类外不能访问
}
int main()
{
	test2();
	system("pause");
	return 0;
}

5.2.9静态成员函数

class Person
{
public:
	static void func()
	{
		m_A = 100;//静态成员函数访问静态成员变量
		//m_B = 200;非静态成员不能被静态函数访问,因为它不知道这是对象p1的还是对象p2的
		cout << "static void func()的调用" << endl;
	}
	static int m_A;
	int m_B;
private:
	static void func2()
	{
		cout << "static void func2()的调用" << endl;
	}
};
int Person:: m_A=10;
void test1()
{
	//1通过对象访问
	Person p1;
p1.func();
	//2通过类名访问
	Person::func();
	//Person::func2(); 因为func2是私有,所以类外不能访问
}
int main()
{
	test1();
	system("pause");
	return 0;
}

5.3c++对象模型和this指针

5.3.1成员变量和成员函数分开存储

class Person
{
	int m_A;//非静态成员属于类的对象上
	static int m_B;//静态成员不属于类的对象上
	void func() {}//非静态成员函数不属于类的对象上
	static void func2() {}//静态成员函数不属于类的对象上
};

5.3.2this指针

	Person& PersonAddAge(Person &p)
	{
		this->age += p.age;//也可以命名规范避免
		return *this;//返回对象本身
	}
void test2()
{
	Person p1(10);
	Person p2(10);
	p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);//链式编程
    //这里会使 p2 的年纪重复加 4 次 ,因为每次的 p2.PersonAddAge(p1) 返回值又是 p2,所以
    //可以继续调用
}

5.3.3空指针调用成员函数

class Person
{
public:
	void shwClassName()
	{
		cout << "this is Person class" << endl;//可以正常访问
	}
	void showPersonAge()
	{
		//报错原因是因为传入的指针为 NULL
		if(this == NULL)
			{
				return ;
			}
		cout << "age = " << m_Age << endl;
	}
	int m_Age;
};
void test1()
{
	Person* p =NULL;
	p->showPersonAge();
	p->shwClassName();//可以正常访问
}

5.3.4const修饰成员函数

class Person
{
public:
	//zhis指针的本质: 指针常量:指针的指向不能修改
	// Person * const this;
	void showPerson1() 
	{
		this->m_A = 100;//正确,因为指针常量可以改变赋值
		//this = NULL 错误,因为指针常量不能改变方向
	}
	// const Person * const this成员函数后加 const 修饰的是 this 指向,让指针指向的值不能改变
	void showPerson2() const
	{
		this->m_B = 100;//加入 mutable 之后才可以修改
		//this->m_A = 100;//错误,因为加入 const 不能改变赋值
		//this = NULL 错误,因为不能改变方向
	}
	void func()
	{
		m_A = 100;
	}

	int m_A;
	mutable int m_B;//特殊变量,即使在常函数中也可以修改
};
//常对象
void test1()
{
	const Person p;
	//p.m_A = 100; p 为常对象,不能修改
	p.m_B = 100;// m_B 在常对象下也可以修改
	//常对象只能调用常函数
	p.showPerson2();
	//p.func  常对象无法调用 非常函数
}


5.4友元

5.4.1全局函数做友元

class Building
{

	friend void goodGay(Building* building);
public:
	string m_SittingRomm;//客厅
private:
	string m_BedRoom;//卧室
public:
	Building()
	{
		m_SittingRomm = "客厅";
		m_BedRoom = "卧室";
	}
};
//全局函数
void goodGay(Building *building)
{
	cout << "好基友全局函数在访问:" << building->m_SittingRomm << endl;
	cout << "好基友全局函数在访问:" << building->m_BedRoom << endl;
}

void test1()
{
	Building building;
	goodGay(&building);
}

5.4.2类做友元

class Building
{
	friend class GoodGay;
public:
	Building();
public:
	string m_SittingRoom;
private:
	string m_BedRoom;
};
class GoodGay
{
public:
	GoodGay();
	void visit();//参观函数 访问 Building 中的属性
	Building* building;
};
//类外写成员函数
Building::Building()
{
	m_SittingRoom = "客厅";
	m_BedRoom = "卧室";
}
GoodGay::GoodGay()
{
	//创建一个建筑物对象
	building = new Building;
}
void GoodGay::visit()
{
	cout << "好基友类正在访问:" << building->m_SittingRoom << endl;
	cout << "好基友类正在访问:" << building->m_BedRoom << endl;
}
void test1()
{
	GoodGay gg;
	gg.visit();
}

5.4.3成员函数做友元

class Building;//!!!需要先声明
class GoodGay
{
public:
	GoodGay();
	void visit1();//让visit1函数访问Building中私有成员
	void visit2();//让visit2函数不能访问Building中私有成员
	Building* building;
};
class Building
{
	friend void GoodGay::visit1();
public:
	Building();
public:
	string m_SittingRoom;
private:
	string m_BedRoom;
};
Building::Building()
{
	m_SittingRoom = "客厅";
	m_BedRoom = "卧室";
}
GoodGay::GoodGay()
{
	building = new Building;
}
void GoodGay::visit1()
{
	cout << "visit1 函数访问:" << building->m_SittingRoom << endl;
	cout << "visit1 函数访问:" << building->m_BedRoom << endl;
}
void GoodGay::visit2()
{
	cout << "visit2 函数访问:" << building->m_SittingRoom << endl;
	//cout << "visit2 函数访问:" << building->m_BedRoom << endl;无法访问,因为没有 friend
}
void test1()
{
	GoodGay gg;
	gg.visit1();
	gg.visit2();
}

5.5运算符重载

5.5.1加号运算符重载

#include <iostream>
using namespace std;


class Person
{
public:
	int m_A;
	int m_B;

	//1,成员函数重载  Person p3=p1.operator+(p2)
	//Person operator+(Person& p)
	//{
	//	Person temp;
	//	temp.m_A = this->m_A + p.m_A;
	//	temp.m_B = this->m_B + p.m_B;
	//	return temp;
	//}
};


//2,全局函数重载  Person p3=operator+(p1,p2)
Person operator+(Person& p1, Person& p2)
{
	Person temp;
	temp.m_A = p1.m_A + p2.m_A;
	temp.m_B = p1.m_B + p2.m_B;
	return temp;
}

	//函数重载版本 person + int
Person operator+(Person& p1, int num)
{
	Person temp;
	temp.m_A = p1.m_A + num;
	temp.m_B = p1.m_B + num;
	return temp;
}
void test1()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;
	Person p2;
	p2.m_A = 10;
	p2.m_B = 10;
	Person p3 = p1 + p2;// person + person
	cout << p3.m_A << ' ' << p3.m_B << endl;

	Person p4 = p1 + 100;// person + int
	cout << p4.m_A << ' ' << p4.m_B << endl;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

5.5.2左移运算符重载

#include <iostream>
using namespace std;
class Person
{
	friend ostream& operator<<(ostream& cout, Person p);

public:
	Person(int a,int b)
	{
		m_A = a;
		m_B = b;
	}
private:
	int m_A;
	int m_B;
	//1,成员函数重载左移运算符,不使用这个方法,因为 p.operator<<(cout) = p<<cout,但需要 cout<<p
	//void operator<<(cout)/{}
};

//2,全局函数左移运算符重载
ostream &operator<<(ostream &cout, Person p)
{
	cout << p.m_A << ' ' << p.m_B;
	return cout;
}

void test1()
{
	Person p1(10,20);

	cout << p1<<endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

5.5.3递增递减运算符重载

#include <iostream>
using namespace std;

class MyInteger
{
	friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
	MyInteger()
	{
		m_Num = 0;
	}

	//重载 前置++运算符,,返回引用是为了一直对一个数据进行控制
	MyInteger& operator++()
	{
		//先进行++运算
		m_Num++;
		//再返回
		return *this;
	}
	//重载 后置++运算符
	//void operator++(int) int代表占位参数,用于区分前置和后置递增
	MyInteger operator++(int)//返回值,不能引用,因为temp这个局部对象会在当前函数执行结束就没了
	{
		//先记录当时结果
		MyInteger temp = *this;
		//后 递增
		m_Num++;
		//最后返回
		return temp;
	}
private:
	int m_Num;
};

ostream& operator<<(ostream& cout, MyInteger myint)
{
	cout << myint.m_Num;
	return cout;
}

void test1()//前置
{
	MyInteger myint;
	cout << ++(++myint) << endl;
	cout << myint << endl;
}
void test2()//后置
{
	MyInteger myint;
	cout << myint++ << endl;
	cout << myint << endl;
}

int main()
{

	test2();
	system("pause");
	return 0;
}
#include <iostream>
using namespace std;


class MyInteger
{
	friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
	MyInteger()
	{
		m_Num = 1;
	}
	MyInteger& operator--()//前置
	{
		m_Num--;
		return *this;
	}
	MyInteger operator--(int)
	{
		MyInteger temp = *this;
		m_Num--;
		return temp;
	}

private:
	int m_Num;
};

ostream& operator<<(ostream& cout, MyInteger myint)
{
	cout << myint.m_Num ;
	return cout;
}

void test1()//前置
{
	MyInteger myint;
	cout << --myint << endl;
	cout << myint << endl;
}
void test2()//后置
{
	MyInteger myint;
	cout << myint-- << endl;
	cout << myint << endl;
}

int main()
{
	test2();

	system("pause");


	return 0;
}

5.5.4赋值运算符重载

#include <iostream>
using namespace std;

class Person
{
public:
	Person(int age)
	{
		m_Age=new int(age);
	}

	Person& operator=(Person& p)
	{
		//应该先判断是否有属性在堆区,如果有先释放,然后再深拷贝
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
		//深拷贝
		m_Age = new int(*p.m_Age);
		return *this;
	}


	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}

	int *m_Age;

};

void test1()
{
	Person p1(18);

	Person p2(20);

	Person p3(22);

	p3=p2 = p1;//赋值操作

	cout << *p1.m_Age << endl;
	cout << *p2.m_Age << endl;
	cout << *p3.m_Age << endl;
}

int main()
{
	test1();

	system("pause");
	return 0;
}

5.5.5关系运算符重载

#include <iostream>
using namespace std;

class Person
{
public:
	string m_Name;
	int m_Age;

	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}

	//重载关系运算符
	bool operator==(Person& p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return true;
		}
		return false;
	}
	bool operator!=(Person& p)
	{
		if (this->m_Name != p.m_Name || this->m_Age != p.m_Age)
		{
			return true;
		}
		return false;
	}

};

void test1()
{
	Person p1("刘家森", 22);
	Person p2("罗灿灿", 21);
	//Person p2("刘家森", 22);
	if (p1 == p2)
	{
		cout << "p1 p2相等" << endl;
	}
	if(p1!=p2)
	{
		cout << "p1 p2不相等" << endl;
	}
}

int main()
{

	test1();
	system("pause");
	return 0;
}

5.5.6函数调用运算符重载

#include <iostream>
using namespace std;

class MyPrint
{
public:
	//重载函数调用运算符
	void operator()(string test)
	{
		cout << test << endl;
	}

};
class MyAdd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}

};
void MyPrint2(string test)
{
	cout <<test << endl;
}
void test1()
{
	MyPrint myPrint;
	
	myPrint("hello world1");//由于使用起来像函数,因此称为 仿函数=重载()之后的函数
	MyPrint2("hello world2");//函数调用
}

void test2()
{
	MyAdd myadd;
	int ret=myadd(100, 100);
	cout << ret << endl;
	//匿名函数对象:没有名字+防函数
	cout << MyAdd()(100, 100) << endl;
}
int main()
{
	test2();

	system("pause");


	return 0;
}

6继承

6.1继承的基本语法

#include <iostream>
using namespace std;

//普通实现页面
class Java
{
public:
	void header()
	{
		cout << "首页,公开课,登陆,注册。。。(公共头部)" << endl;
	}
	void footer()
	{
		cout << "帮助中心,交流合作,站内地图。。。(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,python,C++...(公共分类列表)" << endl;
	}
	void content()
	{
		cout << "java学科" << endl;
	}

};
class Python
{
public:
	void header()
	{
		cout << "首页,公开课,登陆,注册。。。(公共头部)" << endl;
	}
	void footer()
	{
		cout << "帮助中心,交流合作,站内地图。。。(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,python,C++...(公共分类列表)" << endl;
	}
	void content()
	{
		cout << "python学科" << endl;
	}

};
class CPP
{
public:
	void header()
	{
		cout << "首页,公开课,登陆,注册。。。(公共头部)" << endl;
	}
	void footer()
	{
		cout << "帮助中心,交流合作,站内地图。。。(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,python,C++...(公共分类列表)" << endl;
	}
	void content()
	{
		cout << "c++学科" << endl;
	}

};
void test1()
{
	cout << "Java下载视频界面如下: " << endl;
	Java ja;
	ja.header();
	ja.footer();
	ja.left();
	ja.content();
	cout << "------------------------------------" << endl;
	cout << "python下载视频界面如下: " << endl;
	Python py;
	py.header();
	py.footer();
	py.left();
	py.content();
	cout << "------------------------------------" << endl;
	cout << "c++下载视频界面如下: " << endl;
	CPP cp;
	cp.header();
	cp.footer();
	cp.left();
	cp.content();
}



int main()
{
	test1();

	system("pause");


	return 0;
}
#include <iostream>
using namespace std;

//继承实现
class BasePage//公告页面
{
public:
	void header()
	{
		cout << "首页,公开课,登陆,注册。。。(公共头部)" << endl;
	}
	void footer()
	{
		cout << "帮助中心,交流合作,站内地图。。。(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,python,C++...(公共分类列表)" << endl;
	}
};

//java页面
class Java :public BasePage
{
public:
	void content()
	{
		cout << "java学科" << endl;
	}
};
class Python :public BasePage
{
public:
	void content()
	{
		cout << "python学科" << endl;
	}
};
class CPP :public BasePage
{
public:
	void content()
	{
		cout << "c++学科" << endl;
	}
};

void test1()
{
	cout << "Java下载视频界面如下: " << endl;
	Java ja;
	ja.header();
	ja.footer();
	ja.left();
	ja.content();
	cout << "------------------------------------" << endl;
	cout << "python下载视频界面如下: " << endl;
	Python py;
	py.header();
	py.footer();
	py.left();
	py.content();
	cout << "------------------------------------" << endl;
	cout << "c++下载视频界面如下: " << endl;
	CPP cp;
	cp.header();
	cp.footer();
	cp.left();
	cp.content();
}

int main()
{
	test1();

	system("pause");


	return 0;
}

6.2继承方式

#include <iostream>
using namespace std;

class Base1
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

class Son1 : public Base1
{
public:
	void func()
	{
		m_A = 10;//父类中的公共权限到了子类还是公告权限
		m_B = 20;//父类中的保护权限到了子类还是保护权限
		//m_C = 30;父类中的私有权限不能访问
	}
};
class Son2 : protected Base1
{
public:
	void func()
	{
		m_A = 10;//父类中的公共权限到了子类还是保护权限
		m_B = 20;//父类中的保护权限到了子类还是保护权限
		//m_C = 30;父类中的私有权限不能访问
	}
};
class Son3 : private Base1
{
public:
	void func()
	{
		m_A = 10;//父类中的公共权限到了子类还是私有权限
		m_B = 20;//父类中的保护权限到了子类还是私有权限
		//m_C = 30;父类中的私有权限不能访问
	}
};

class GrandSon3 : private Son3
{
public:
	void func()
	{
		//m_A = 10;//父类中的私有权限到了子类不能访问
		//m_B = 20;//父类中的私有权限到了子类不能访问
	}
};

void test1()
{
	Son1 s1;
	s1.m_A = 100;//公告权限在类内类外都可以访问
	//s1.m_B = 100;保护权限在类内可以访问,类外不能
}
void test2()
{
	Son2 s2;
	//s2.m_A = 100; //保护权限在类内可以访问,类外不能
}
void test3()
{
	Son3 s3;
	//s3.m_A = 100;//私有权限在类内可以访问,类外不能
}
int main()
{


	system("pause");


	return 0;
}

6.3继承中的对象模型

#include <iostream>
using namespace std;

class Base
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

class Son1 : public Base
{
public:
	int m_D;
};
//利用开发人员工具查看对象模型
//1.找到文件
//2. cl /d1 reportSingleClassLayout类名 文件名
void test1()
{
	//父类中所有非静态成员属性都会被子类继承,私有成员被继承,但无法访问
	cout << "siezof son: " << sizeof(Son1) << endl;
}
int main()
{
	test1();

	system("pause");


	return 0;
}

6.4继承中构造和析构顺序

#include <iostream>
using namespace std;

class Base
{
public:
	Base()
	{
		cout << "Base构造函数" << endl;
	}
	~Base()
	{
		cout << "Base析构函数" << endl;
	}
};
class Son1 : public Base
{
public:
	Son1()
	{
		cout << "Son1构造函数" << endl;
	}
	~Son1()
	{
		cout << "Son1析构函数" << endl;
	}
};
void test1()
{
	//Base b;
	Son1 s1;
}

int main()
{

	test1();
	system("pause");


	return 0;
}

6.5继承同名成员处理方式

#include <iostream>
using namespace std;

class Base
{
public:
	Base()
	{
		m_A = 100;
	}
	void func()
	{
		cout << "Base函数调用" << endl;
	}
	void func(int a)
	{
		cout << "Baseint函数调用" << endl;
	}
	int m_A;
};
class Son1 : public Base
{
public:
	Son1()
	{
		m_A = 200;
	}
	void func()
	{
		cout << "son函数调用" << endl;
	}

	int m_A;
};

void test1()//同名成员属性
{
	Son1 s1;
	cout <<"son:"<< s1.m_A << endl;//直接访问是访问子类的
	cout <<"base"<< s1.Base::m_A<< endl;//加作用域是访问父类的
}
//如果子类中出现和父类同名函数,子类函数会隐藏父类所以同名(包括重载)函数
void test2()//同名成员方法
{
	Son1 s2;
	s2.func();//直接访问是访问子类的
	s2.Base::func();//加作用域是访问父类的
	s2.Base::func(100);//加作用域是访问父类的
}
int main()
{
	test2();

	system("pause");


	return 0;
}

6.6.继承同名静态成员处理方式

#include <iostream>
using namespace std;

class Base
{
public:
	static int m_A;
	static void func()
	{
		cout << "Base下" << endl;
	}
	static void func(int a)
	{
		cout << "Baseint下" << endl;
	}
};
int Base::m_A = 100;

class Son1 : public Base
{
public:
	static int m_A;
	static void func()
	{
		cout << "Son1下" << endl;
	}


};
int Son1::m_A = 200;
//同名静态成员属性
void test1()
{
	//1,通过对象访问静态成员
	Son1 s1;
	cout << "通过对象访问" << endl;
	cout << s1.m_A << endl;
	cout << s1.Base::m_A << endl;
	//2,通过类名访问静态成员
	cout << "通过类名访问" << endl;
	cout << Son1::m_A << endl;
	//第一个::代表通过类名访问,第二个::代表访问父类作用域下
	cout << Son1::Base::m_A << endl;

}
//同名静态成员函数
void test2()
{
	//1,通过对象访问
	Son1 s1;
	s1.func();
	s1.Base::func();
	//2,通过类名访问
	Son1::func();
	Son1::Base::func();
	 Son1::Base::func(100);
}


int main()
{
	test2();

	system("pause");


	return 0;
}

6.7多继承语法

#include <iostream>
using namespace std;

class Base1
{
public:
	Base1()
	{
		m_A = 100;
	}
	int m_A;
};
class Base2
{
public:
	Base2()
	{
		m_A = 200;
	}
	int m_A;
};
class Son : public Base1, public Base2
{
public:
	Son()
	{ 
		m_C = 300;
		m_D = 400;
	}
	int m_C;
	int m_D;

};

void test1()
{
	Son s;
	cout << "sizeof: " << sizeof(Son) << endl;
	cout << s.Base1::m_A << endl;
	cout << s.Base2::m_A << endl;
}
int main()
{

	test1();
	system("pause");


	return 0;
}

6.8菱形继承

#include <iostream>
using namespace std;

//动物类
class Animal
{
public:
	int m_Age;
};
//利用虚继承,解决菱形继承问题,在继承方式之前加 virtual
// 虚继承
// vbptr:虚基类指针
//羊类
class Sheep : virtual public Animal
{

};
//驼类
class Tuo : virtual public Animal
{

};
//羊驼类
class SheepTuo : public Sheep, public Tuo
{

};
void test1()
{
	SheepTuo st;
	st.Sheep::m_Age = 18;
	st.Tuo::m_Age = 28;
	//当出现菱形继承的时候,有两个父类拥有相同数据时,需要加作用域
	cout << st.Sheep::m_Age << endl;
	cout << st.Tuo::m_Age << endl;
	cout << st.m_Age << endl;
	//菱形继承数据有两份,导致资源浪费
}

int main()
{
	test1();

	system("pause");


	return 0;
}

7多态

7.1多态的基本使用

#include <iostream>
using namespace std;

class Animal
{
public:
	virtual void speak()//虚函数
	{
		cout << "动物在说话" << endl;
	}

};

class Cat : public Animal
{
public:
	void speak()
	{
		cout << "小猫在喵喵喵" << endl;
	}
};
class Dog : public Animal
{
public:
	void speak()
	{
		cout << "小狗在汪汪汪" << endl;
	}
};

//执行说话的函数
//地址早绑定,在编译阶段就确定函数地址
//如果想让 猫 说话,这个函数地址不能提前绑定,需要在运行时绑定=地址软绑定
//动态多态的条件:(1)有继承关系。(2)子类重写父类虚函数,父类的函数加 virtual,子类加不加无所谓。
//动态多态使用:(1)父类的指针或者引用,执行子类对象
void doSpeak(Animal& animal) //Animal &animal = cat,,,,父类引用可以传子类
{
	animal.speak();
}
void test1()
{
	Cat cat;
	Dog dog;
	Animal animal;
	doSpeak(animal);
	doSpeak(dog);
	doSpeak(cat);
}
int main()
{
	test1();

	system("pause");


	return 0;
}

7.2多态使用的原理

7.3纯虚函数和抽象类

#include <iostream>
using namespace std;


//纯虚函数和抽象类
class Base
{
public:
	//只要有一个纯虚函数,这个类叫抽象类
	//1,无法实例化对象
	//2,抽象类子类,必须要重写父类中的纯虚函数,否则该子类也为抽象类
	virtual void func() = 0;//纯虚函数语法

};
class Son : public Base
{
public:

};
class Daughter : public Base
{
public:
	virtual void func()
	{
		cout << "调用" << endl;
	}
};
void test1()
{
	//Base b;//纯虚函数无法实例化对象
	//new Base//纯虚函数无法实例化对象
	//Son s;//抽象类子类,必须要重写父类中的纯虚函
}
void test2()
{
	//对象访问
	Daughter d;//子类重写了父类纯虚函数
	d.func();
	//指针访问
	Base* base = new Daughter;
	base->func();
	delete base;


}
int main()
{
	test2();

	system("pause");


	return 0;
}

7.4虚析构和纯虚析构

#include <iostream>
using namespace std;

class Animal
{
public:
	Animal()
	{
		cout << "Animal的构造函数调用" << endl;
	}
	//利用虚析构解决 父类指针释放子类对象时不干净问题
	//virtual ~Animal()
	//{
	//	cout << "Animal的析构函数调用" << endl;
	//}
	virtual ~Animal() = 0;//纯虚析构:1,需要声明,2,需要实现。有了纯虚析构之后,该类也为抽象类,无法实例化对象
	virtual void speak() = 0;

};
Animal::~Animal()
{
	cout << "Animal的纯虚析构函数调用" << endl;
}
class Cat : public Animal
{
public:
	Cat(string name)
	{
		cout << "cat的构造函数调用" << endl;
		m_Name = new string(name);
	}
	virtual void speak()
	{
		cout << *m_Name<<"喵喵喵" << endl;
	}
	~Cat()
	{
		if (m_Name != NULL)
		{
			cout << "cat析构调用" << endl;
			delete m_Name;
			m_Name = NULL;
		}
	}
	string *m_Name;
};
void test1()
{
	Animal* animal = new Cat("灿灿");
	animal->speak();
	//父类指针在析构时,不会调用子类析构
	delete animal;
}
int main()
{
	test1();

	system("pause");


	return 0;
}

8文件操作

8.1文本文件

8.1.1写文件

写文件步骤
1.包含头文件fstream#include <fstream>
2.创建 流对象ofstream ofs;
3.指定打开方式ofs.open("test.txt", ios::out);
//4.写内容ofs << "姓名:刘家森" << endl;
//5.关闭文件    ofs.close();

8.1.2读文件

读文件步骤
1.包含头文件fstream#include <fstream>
2.创建 流对象ifstream ifs;
3.打开文件并判断打开是否成功ifs.open("文件路径", 打开方式);
//4.读数据四种方式
//5.关闭文件    ifs.close();

	char buf[1024] = { 0 };
	while (ifs >> buf)
	{
		cout << buf << endl;
	}

	char buf[1024] = { 0 };
	while (ifs.getline(buf, sizeof(buf)))
	{
		cout << buf << endl;
	}

	string buf;
	while (getline(ifs, buf))
	{
		cout << buf << endl;
	}

	char c;
	while ((c = ifs.get()) != EOF)//如果没读到文件尾,EOF=end of line
	{
		cout << c;
	}

#include <iostream>
using namespace std;
#include <fstream>
#include <string>

void test1()
{
	//1.包含头文件
	//2.创建流对象
	ifstream ifs;
	//打开文件,并且判断是否成功
	ifs.open("test.txt", ios::in);
	if (!ifs.is_open())
	{
		cout << "文件打开失败" << endl;
		return;
	}
	//4.读数据
	///1
	//char buf[1024] = { 0 };
	//while (ifs >> buf)
	//{
	//	cout << buf << endl;
	//}
	///2
	//char buf[1024] = { 0 };
	//while (ifs.getline(buf, sizeof(buf)))
	//{
	//	cout << buf << endl;
	//}
	///3
	//string buf;
	//while (getline(ifs, buf))
	//{
	//	cout << buf << endl;
	//}
	///4 不推荐
	//char c;
	//while ((c = ifs.get()) != EOF)//如果没读到文件尾,EOF=end of line
	//{
	//	cout << c;
	//}
	//5.关闭文件
	ifs.close();
}

int main()
{
	test1();

	system("pause");


	return 0;
}

8.2二进制文件

8.2.1写文件

#include <iostream>
using namespace std;
#include <fstream>
class Person
{
public:
	char m_Name[64];
	int m_Age;
};


void test1()
{
	//1.包含头文件
	//2.创建流对象
	ofstream ofs("Person.txt", ios::binary | ios::out);// 2,3步骤和为一起
	//3.打开文件
	//ofs.open("Person.txt", ios::binary | ios::out);
	//4.写文件
	Person p = { "刘家森",22 };

	ofs.write((const char*)&p, sizeof(p));//取地址后强转为 const char *
	//5.关闭文件
	ofs.close();
}

int main()
{
	test1();

	system("pause");


	return 0;
}

8.2.2读文件

#include <iostream>
using namespace std;
#include <fstream>
#include <string>

class Person
{
public:
	char m_Name[64];
	int m_Age;

};

void test1()
{
	//1.头文件
	//2.创建流对象
	ifstream ifs;
	//3.打开文件,并判断打开成功是否
	ifs.open("Person.txt", ios::binary | ios::in);
	if (!ifs.is_open())
	{
		cout << "打开失败"<<endl;
		return; 
	}
	//4.读文件
	Person p;
	ifs.read((char* )&p, sizeof(p));
	cout << "姓名:" << p.m_Name << "年龄:" << p.m_Age << endl;
	//5.关闭文件
	ifs.close();
}

int main()
{
	test1();

	system("pause");


	return 0;
}

9模板

9.1模板的概念

9.2函数模板

9.2.1函数模板语法

#include <iostream>
using namespace std;

//函数模板
template<typename T>//声明一个模板,告诉编译器后面代码中紧跟着的T不用报错,T是一个通用数据
void MySwap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}

void test1()
{
	int a = 10;
	int b = 20;
	//两种方式使用函数模板
	//1.自动类型推导
	//MySwap(a,b);
	cout << a << " " << b<<endl;
	double c = 3.1;
	double d = 4.1
	//2.显示指定类型
	MySwap<double>(c, d);
	cout << c << " " << d << endl;
}
int main()
{

	test1();
	system("pause");


	return 0;
}

9.2.2函数模板注意事项

#include <iostream>
using namespace std;

template<class T>//typename 可以替换为 class
void MySwap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}
//1.自动类型推导,必须推导出一致的数据类型才可以使用
void test1()
{
	int a = 10;
	int b = 20;
	char c = 'c';
	MySwap(a, b);//正确
	//MySwap(a, c);//错误,数据类型不一致
	cout << a << " " << b << endl;
}
//2.模板必须要确定出 T 的数据类型才可以使用
template<class T>
void func()
{
	cout << "func的调用" << endl;
}
void test2()
{
	//func();//错误,没用指定 T 的数据类型
	func<int>();//正确
}
int main()
{
	test2();

	system("pause");


	return 0;
}

9.2.3普通函数和函数模板区别

#include <iostream>
using namespace std;

//普通函数
int MyAdd1(int a, int b)
{
	return a + b;
}
void test1()
{
	int a = 10;
	int b = 20;
	char c = 'a';// a 的 ASCALL是97
	cout << MyAdd1(a, b) << endl;
	cout << MyAdd1(a, c) << endl;//字符型隐式转为了整型
}
//函数模板自动类型推导
template<class T>
T MyAdd2(T a, T b)
{
	return a + b;
}
void test2()
{
	cout << MyAdd2(1, 2) << endl;//正常输出两个 整型
	//cout << MyAdd2(1, 'a') << endl;函数不清楚里面什么转什么
}
//函数模板显示指定类型
template<class T>
T MyAdd3(T a, T b)
{
	return a + b;
}
void test3()
{
	cout << MyAdd3<int>(1, 2) << endl;//正常输出两个 整型
	cout << MyAdd3<int>(1, 'a') << endl;//发生了隐式转换
}
int main()
{
	test1();
	test2();
	test3();
	system("pause");


	return 0;
}

9.2.4普通函数和函数模板的调用规则

#include <iostream>
using namespace std;


void MyPrint(int a, int b)
{
	cout << "调用普通函数" << endl;
}
template<class T>
void MyPrint(T a, T b)
{
	cout << "调用的模板" << endl;
}
template<class T>//函数重载
void MyPrint(T a, T b,T c)
{
	cout << "调用的重载模板" << endl;
}
void test1()
{
	int a = 10;
	int b = 20;
	//MyPrint(a, b);

	//通过空模板参数列表,强制调用函数模板
	//MyPrint<>(a, b);
	//函数重载
	//MyPrint(a, b, 1);
	//如果函数模板产生更好的匹配,优先掉函数模板,这里普通函数是 int,模板是 T,所以优先选择 T
	char c1 = 'a';
	char c2 = 'b';
	MyPrint(c1, c2);
}
int main()
{
	test1();

	system("pause");


	return 0;
}

9.2.5模板的局限性

#include <iostream>
using namespace std;


class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}
	string m_Name;
	int m_Age;

};

template<class T>
bool MyCompare(T& a, T& b)
{
	if (a == b)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//利用具体化Person的版本来实现代码,优先调用
template<>  bool MyCompare(Person& p1, Person& p2)
{
	if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void test1()
{
	int a = 10;
	int b = 10;
	bool ret = MyCompare(a, b);
	if (ret)
	{
		cout << "a和b相等" << endl;
	}
	else
	{
		cout << "a和b不相等" << endl;
	}
}
void test2()
{
	Person p1("tom", 10);
	Person p2("tom", 10); 
	bool ret = MyCompare(p1,p2);
	if (ret)
	{
		cout << "p1和p2相等" << endl;
	}
	else
	{
		cout << "p1和p2不相等" << endl;
	}
}
int main()
{
	test1();
	test2();

	system("pause");


	return 0;
}

9.3类模板

9.3.1类模板语法

template <class NameTyep, class AgeType>
class Person
{
public:
	Person(NameTyep name, AgeType age)
	{
		m_Name = name;
		m_Age = age;
	}
	void showPerson()
	{
		cout << m_Name << ' ' << m_Age << endl;
	}

	NameTyep m_Name;
	AgeType m_Age;
};
#include <iostream>
using namespace std;

template <class NameTyep, class AgeType>
class Person
{
public:
	Person(NameTyep name, AgeType age)
	{
		m_Name = name;
		m_Age = age;
	}
	void showPerson()
	{
		cout << m_Name << ' ' << m_Age << endl;
	}

	NameTyep m_Name;
	AgeType m_Age;
};


void test1()
{
	Person<string, int> p1("张三", 22);
	p1.showPerson();
}
int main()
{
	test1();

	system("pause");


	return 0;
}

9.3.2类模板于函数模板区别

#include <iostream>
using namespace std;

template <class NameType, class AgeType=int>//这里赋值了 int
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		m_Name = name;
		m_Age = age;
	}
	void ShowPerson()
	{
		cout << m_Name<< ' ' <<m_Age << endl;
	}
	NameType m_Name;
	AgeType m_Age;
};
//1.类模板没有自动推导
void test1()
{

	//Person p("孙悟空", 100);错误,无法自动推导
	Person<string, int>p("孙悟空", 100);//正确,只能用显示指令
	p.ShowPerson();
}
//2.类模板在模板参数列表中可以有默认参数
void test2()
{
	Person<string>p("猪八戒", 99);//因为默认出写了 int,这里可以写也可以不写
	p.ShowPerson();
}
int main()
{
	test1();
	test2();
	system("pause");


	return 0;
}

9.3.3类模板中成员函数创建时机

#include <iostream>
using namespace std;

class Person1
{
public:
	void ShowPerson1()
	{
		cout << "p1 show" << endl;
	}
};
class Person2
{
public:
	void ShowPerson2()
	{
		cout << "p2 show" << endl;
	}
};
template<class T>
class MyClass
{
public:
	T obj;
	//类模板中的成员函数
	void func1()
	{
		obj.ShowPerson1();
	}
	void func2()
	{
		obj.ShowPerson2();
	}
};
void test1()
{
	MyClass<Person1>m;
	m.func1();
	//m.func2();错误,因为此时的 m 是 Person1 类型,不能访问 Person2 类型
}
int main()
{

	test1();
	system("pause");


	return 0;
}

9.3.4类模板对象做函数参数

#include <iostream>
#include <string>
using namespace std;
//类模板对象做函数参数
template<class T1,class T2>
class Person
{
public:
	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	void ShowPerson()
	{
		cout << this->m_Name<<" " << this->m_Age << endl;
	}
	T1 m_Name;
	T2 m_Age;
};
//1.指定传入类型
void PrintPerson1(Person<string, int>&p)
{
	p.ShowPerson();
}
void test1()
{
	Person<string,int>p("孙悟空", 99);
	PrintPerson1(p);
}
//2.参数模板化
template<class T1,class T2>
void PrintPerson2(Person<T1, T2>& p)
{
	
	p.ShowPerson();
	cout << "T1类型:" << typeid(T1).name() << endl;//查看 T1 类型
	cout << "T2类型:" << typeid(T2).name() << endl;//查看 T2 类型

}
void test2()
{
	Person<string, int>p("猪八戒", 100);
	PrintPerson2(p);
}
//3.整个类模板化
template<class T>
void PrintPerson3(T &p)
{
	p.ShowPerson();
	cout << "T1类型:" << typeid(T).name() << endl;//查看 T1 类型
}
void test3()
{
	Person<string, int>p("唐僧", 10);
	PrintPerson3(p);
}

int main()
{
	test1();
	test2();
	test3();
	system("pause");


	return 0;
}

9.3.5类模板与继承

#include <iostream>
using namespace std;

template<class T>
class Base
{
public:
	T m;
};
//class Son : public Base//错误 ,必须要知道父类中 T 的类型才能继承给子类
class Son : public Base<int>//正确 ,必须要知道父类中 T 的类型才能继承给子类
{

};
void test1()
{
	Son s1;

}
//如果要灵活指定父类中 T 的类型,子类也需要变类模板
template<class T1,class T2>
class Son2 : public Base<T2>
{
public:
	Son2()
	{
		cout << "T1类型:" << typeid(T1).name() << endl;
		cout << "T2类型:" << typeid(T2).name() << endl;
	}
	T1 obj;
};
void test2()
{
	Son2<int, char>s2;
}
int main()
{
	test1();
	test2();
	system("pause");
	return 0;
}

9.3.6类模板成员函数类外实现

#include <iostream>
using namespace std;

template<class T1,class T2>
class Person
{
public:
	Person(T1 name, T2 age);
	//{
	//	m_Name = name;
	//	m_Age = age;
	//}
	void showPerson();
	//{
	//	cout << "姓名:" << m_Name << "年龄:"m_Age << endl;
	//}
	T1 m_Name;
	T2 m_Age;

};
//构造函数类外实现
template<class T1,class T2>
Person<T1,T2>::Person(T1 name, T2 age)
{
	m_Name = name;
	m_Age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
	cout << "姓名:" << m_Name << "年龄:"<<m_Age << endl;
}
void test1()
{
	Person<string, int>p("ljs", 20);
	p.showPerson();
}
int main()
{
	test1();
	system("pause");
	return 0;
}

9.3.7类模板分文件编写

9.3.8类模板与友元

#include <iostream>
using namespace std;
#include <string>
//提前让编译器知道 person 类的存在
template<class T1, class T2>
class Person;

//通过 全局函数 打印Person信息
template<class T1, class T2>
void PrintPerson2(Person<T1, T2>p)
{
	cout << "类外实现" << p.m_Name << ' ' << p.m_Age << endl;
}

template<class T1,class T2>
class Person
{
	//全局函数 类内实现
	friend void PrintPerson(Person<T1, T2>p)
	{
		cout << "类内实现" << p.m_Name << ' ' << p.m_Age << endl;
	}
	//全局函数 类外实现
	//如果全局函数 类外实习按 需要要编译器提前知道这个函数存在
	friend void PrintPerson2<>(Person<T1, T2>p);//加空模板参数列表
public:
	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
private:
	T1 m_Name;
	T2 m_Age;
};

void test1()
{
	Person<string, int>p("tom", 20);
	PrintPerson(p);
}
void test2()
{
	Person<string, int>p("刘家森", 22);
	PrintPerson2(p);
}
int main()
{
	test1();
	test2();
	system("pause");
	return 0;
}

10STL-常用容器

10.1STL初始

10.1.1STL的诞生

10.1.2STL基本概念

10.1.3STL六大组件

10.2STL中容器,算法,迭代器

10.2.1STL中容器,算法,迭代器概念

10.2.2vector存放内置数据类型


	通过迭代器访问容器数据
	vector<int>::iterator itBegin = v.begin();//begin=起始迭代器,指向容器第一个元素    iterator:迭代器名字
	vector<int>::iterator itEnd = v.end();//end=结束迭代器,指向容器最后一个元素的下一个位置
	//第一种遍历方式
	while (itBegin != itEnd)
	{
		cout << *itBegin << endl;
		itBegin++;
	}
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << endl;
	}
for_each(v.begin(), v.end(), MyPrint);
void MyPrint(int val)
{
	cout << val << endl;
}
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>

void MyPrint(int val)
{
	cout << val << endl;
}


void test1()
{
	//创建了一个 vector 容器=数组
	vector<int> v;
	//向容器中插入数据(尾插法)
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	//通过迭代器访问容器数据
	//vector<int>::iterator itBegin = v.begin();//begin=起始迭代器,指向容器第一个元素    iterator:迭代器名字
	//vector<int>::iterator itEnd = v.end();//end=结束迭代器,指向容器最后一个元素的下一个位置
	第一种遍历方式
	//while (itBegin != itEnd)
	//{
	//	cout << *itBegin << endl;
	//	itBegin++;
	//}
	第二种遍历方式
	//for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	//{
	//	cout << *it << endl;
	//}
	//第三种遍历方式,利用 STL 提供的遍历算法
	for_each(v.begin(), v.end(), MyPrint);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.2.3vector存放自定义数据类型

#include <iostream>
using namespace std;
#include <vector>

class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}
	string m_Name;
	int m_Age;
};

void test1()
{
	vector<Person>v;
	Person p1("a", 10);
	Person p2("b", 20);
	Person p3("c", 30);
	Person p4("d", 40);
	Person p5("e", 50);
	//向容器添加数据
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);
	//遍历容器数据
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		//cout << (*it).m_Name<<' '<<(*it).m_Age << endl;//通过解引用访问
		cout << it->m_Name << ' ' << it->m_Age << endl;//通过指针访问
	}
}
//存放自定义数据类型指针
void test2()
{
	vector<Person*>v;
	Person p1("a", 10);
	Person p2("b", 20);
	Person p3("c", 30);
	Person p4("d", 40);
	Person p5("e", 50);
	//向容器添加数据
	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);
	v.push_back(&p4);
	v.push_back(&p5);
	//遍历容器数据
	for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << (*it)->m_Name << ' ' << (*it)->m_Age << endl;
	}
}
int main()
{
	test2();
	system("pause");
	return 0;
}

10.2.4vector容器嵌套容器

#include <iostream>
using namespace std;
#include<vector>

void test1()
{
	vector<vector<int>> v;
	//创建小容器
	vector<int> v1;
	vector<int> v2;
	vector<int> v3;
	vector<int> v4;
	//向小容器添加数据
	for (int i = 0; i < 4; i++)
	{
		v1.push_back(i + 1);
		v2.push_back(i + 2);
		v3.push_back(i + 3);
		v4.push_back(i + 4);
	}
	//将小容器插入到大容器
	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);
	v.push_back(v4);
	//通过大容器将数据遍历
	for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
	{
		//(*it)=小容器vector<int>
		for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
		{
			cout << *vit << " ";
		}
		cout << endl;
	}
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.3string容器

10.3.1string容器基本概念

10.3.2string构造函数

#include <iostream>
using namespace std;

//string的构造函数
void test1()
{
	string s1;//默认构造
	const char* str = "hello world";
	string s2(str);//字符串初始化
	cout << s2 << endl;
	string s3(s2);//拷贝构造
	cout << s3 << endl;
	string s4(10, 'a');
	cout << s4 << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.3.3string赋值操作

#include <iostream>
using namespace std;

void test1()
{
	//1.string& operator=(const char *s)把char* 类型字符串 赋值给当前的字符串
	string str1;
	str1 = "hello world";
	cout << str1 << endl;
	//2.string& operator=(const string &s)把字符串s赋给当前的字符串
	string str2;
	str2 = str1;
	cout << str2 << endl;
	//3.string& operator=(char c) 把字符赋值给字符串
	string str3;
	str3 = 'a';
	cout << str3<<endl;
	//4.string& assign=(const char *s)把字符串s赋给当前的字符串
	string str4;
	str4.assign("hello C++");
	cout << str4 << endl;
	//5.string& assign=(const char *s,int n)把字符串s的前n个字符赋给当前字符
	string str5;
	str5.assign("Hello C++", 5);
	cout << str5 << endl;
	//6.string& assign=(const string *s)把字符串s赋给当前的字符串
	string str6;
	str6.assign(str5);
	cout << str6 << endl;
	//7.string& assign=(int n,char c) 把n个字符c赋值给当前字符串
	string str7;
	str7.assign(6, 'c');
	cout << str7 << endl;
}


int main()
{
	test1();
	system("pause");
	return 0;
}

10.3.4string字符串拼接

#include <iostream>
using namespace std;


void test1()
{
	//1.string& operator+=(const char * str)  重载+=操作符  字符串
	string str1 = "我";
	str1 += "爱玩游戏";
	cout << str1 << endl;
	//2.string& operator+=(const char c)  重载+=操作符  单字符
	str1 += ':';
	cout << str1 << endl;
	//3.string& operator+=(const string& str)  重载+=操作符 字符串变量
	string str2 = "LOL";
	str1 += str2;
	cout << str1 << endl;
	//4.string& append(const char *s) 把字符串s连接到当前字符串末尾
	string str4="我爱";
	str4.append("罗灿灿");
	cout << str4 << endl;
	//5.string& append(const char *s,int n) 把字符串s的前n个字符连接到当前字符串末尾
	string str5 = "我爱";
	str5.append("lccc", 2);//注意事项:1中文=2字符
	cout << str5 << endl;
	//6.string& append(const string &s)  把s字符串变量赋值给当前字符串
	string str6;
	str6.append(str5);
	cout << str6 << endl;
	//7.string& append(const string &s,int pos,int n) 字符串s中从pos开始的n给字符连接到字符串结尾
	string str7 = "wo ai ni";
	string str8="wo ";
	str8.append(str7,3, 5);//注意事项:从 0 开始
	cout << str8 << endl;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.3.5string查找和替换

#include <iostream>
using namespace std;
//1.查找
void test1()
{
	string str1 = "abcdefgde";
	int pos =str1.find("de");//找到返回第一个字符下标,没找到返回-1
	if (pos == -1)
	{
		cout << "没找到字符串" << endl;
	}
	else
	{
		cout <<"找到字符串" <<pos << endl;
	}
	//rfind 从右往左取最后一个   find相反
	pos = str1.rfind("de");
	cout << pos << endl;
}
//2.替换
void test2()
{
	string str2 = "abcdefg";
	str2.replace(1, 3, "1111");//从 1 号位置开始 把 后面三个原字符 替换为 1111
	cout << str2 << endl;
}
int main()
{
	test1();
	test2();
	system("pause");
	return 0;
}

10.3.6string字符串比较

#include <iostream>
using namespace std;

void test1()
{
	string str1 = "aello";
	string str2 = "xello";
	if (str1.compare(str2) == 0)
	{
		cout << "两者相同" << endl;
	}
	else if (str1.compare(str2) > 0)
	{
		cout << "str1大" << endl;
	}
	else
	{
		cout << "str2大" << endl;
	}
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.3.7string字符读写

#include <iostream>
using namespace std;

void test1()
{
	string str1 = "hello world";
	cout << str1 << endl;
	//1.通过【】访问单个字符
	for (int i = 0; i < str1.size(); i++)
	{
		cout << str1[i] << ' ';
	}
	cout << endl;
	//2.通过at方式访问单个字符
	for (int i = 0; i < str1.size(); i++)
	{
		cout << str1.at(i) << ' ';
	}
	cout << endl;
	//修改单个字符
	str1[0] = 'x';
	cout << str1 << endl;
	//
	str1.at(1) = 'x';
	cout << str1 << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.3.8string插入和删除

#include <iostream>
using namespace std;

void test1()
{
	string str1 = "hello";
	//插入
	str1.insert(1, "111");//从 第一位 开始插入(没有第0位)
	cout << str1 << endl;
	//删除
	str1.erase(1, 3);
	cout << str1 << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.3.9string子串

#include <iostream>
using namespace std;

void test1()
{
	string str = "abcdef";
	string str1 = str.substr(0, 3);
	cout << str1 << endl;
}
//实用操作:从邮件地址获取姓名
void test2()
{
	string str1 = "zhangsan@sina.com";
	int pos = str1.find("@");
	string usrName = str1.substr(0, pos);
	cout << usrName << endl;
}

int main()
{
	test1();
	test2();
	system("pause");
	return 0;
}

10.4vector容器

10.4.1vector基本概念

10.4.2vector构造函数

#include <iostream>
using namespace std;
#include<vector>

void PrintVector(vector<int> &v)
{
	for (vector<int>::iterator it= v.begin(); it != v.end(); it++)
	{
		cout <<*it<< ' ';
	}
	cout << endl;
}
void test1()
{
	//默认构造
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	PrintVector(v1);

	//通过区间构造
	vector<int>v2(v1.begin(), v1.end());
	PrintVector(v2);
	//n个elem方式构造
	vector<int>v3(10, 100);//将 10 个 100 传入
	PrintVector(v3);
	//拷贝构造
	vector<int>v4(v3);
	PrintVector(v4);
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.4.3vector赋值操作

#include <iostream>
using namespace std;
#include<vector>

void PrintVector(vector<int> &v)
{
	for (vector<int>::iterator it= v.begin(); it != v.end(); it++)
	{
		cout <<*it<< ' ';
	}
	cout << endl;
}
void test1()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	PrintVector(v1);
	//赋值 =
	vector<int>v2;
	v2 = v1;
	PrintVector(v2);
	//赋值 assign 区间赋值
	vector<int>v3;
	v3.assign(v1.begin(), v1.end());
	PrintVector(v3);
	//赋值 aasign n个elem方式
	vector<int>v5;
	v5.assign(5,1);
	PrintVector(v5);
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.4.4vector容量和大小

#include <iostream>
using namespace std;
#include<vector>

void PrintVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
void test1()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	PrintVector(v1);
	//容量大小判断
	if (v1.empty())//为真,代表容器为空
	{
		cout << "v1为空" << endl;
	}
	else
	{
		cout << "v1不为空" << endl;
		cout << "v1容量:" << v1.capacity() << endl;
		cout << "v1大小:" << v1.size() << endl;
	}
	//重新指定大小
	v1.resize(15);
	PrintVector(v1);//扩大后的值为默认值 0
	v1.resize(20, 1);//扩大后的值为 1
	PrintVector(v1);
	v1.resize(5);
	PrintVector(v1);//重新指定之后内存变小了,则去掉多余部分
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.4.5vector插入和删除

#include <iostream>
using namespace std;
#include<vector>

void PrintVector(vector<int>&v)
{
	for (vector<int>::iterator it = v.begin(); it!= v.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
void test1()
{
	vector<int>v1;
	//尾插法
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	PrintVector(v1);
	//尾删法
	v1.pop_back();
	PrintVector(v1);
	//迭代器头部插入 单个
	v1.insert(v1.begin(), 10);//第一个参数是 迭代器
	PrintVector(v1);
	//迭代器头部插入 多个
	v1.insert(v1.begin(), 2, 100);//从开始位置 插入 2 个 100;
	PrintVector(v1);
	//删除 单个
	v1.erase(v1.begin());//删除头部第一个
	PrintVector(v1);
	//删除 多个
	v1.erase(v1.begin(),v1.end());//删除从头到尾
	PrintVector(v1);
	//清空
	v1.clear();
	PrintVector(v1);

}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.4.6vector数据读写

#include <iostream>
using namespace std;
#include<vector>

void PrintVector(vector<int>&v)
{
	for (vector<int>::iterator it = v.begin(); it!= v.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	cout << "交换前" << endl;
	PrintVector(v1);
	vector<int>v2;
	for (int i = 10; i > 0; i--)
	{
		v2.push_back(i);
	}
	PrintVector(v2);
	cout << "交换后" << endl;
	v1.swap(v2);
	PrintVector(v1);
	PrintVector(v2);
}

//实际用途,收缩内存空间
void test2()
{
	vector<int>v1;
	for (int i = 0; i < 100000; i++)
	{
		v1.push_back(i);
	}
	cout << v1.capacity() << endl;
	cout << v1.size() << endl;

	v1.resize(3);//重新指定大小
	cout << v1.capacity() << endl;
	cout << v1.size() << endl;
	//利用swap收缩
	vector<int>(v1).swap(v1);//vector<int>(v1)是创建匿名对象x,x根据v1大小创建合适对象。swap(v1)
	cout << v1.capacity() << endl;
	cout << v1.size() << endl;
}
int main()
{
	test2();
	system("pause");
	return 0;
}

10.4.8vector预留空间

#include <iostream>
using namespace std;
#include<vector>

void test1()
{
	vector<int>v1;
	//利用reserve预留10000空间,内存空间一次就分配够
	v1.reserve(100000);
	int num=0;
	int* p = NULL;

	for (int i = 0; i < 100000; i++)
	{
		v1.push_back(i);
		if (p != &v1[0])//当指针不知向数组首地址时,就重新指向一次,实现计数内存空间改变了几次
		{
			p = &v1[0];
			num++;
		}
	}
	cout << num << endl;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.5deque容器

10.5.1deque容器基本概念

10.5.2deque构造函数

#include <iostream>
using namespace std;
#include<deque>

void PrintDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)//加入const防止修改数据,这里是只读
	{
		cout << *it << ' ';
	}
	cout << endl;
}
void test1()
{
	deque<int>d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	PrintDeque(d1);
	//区间赋值
	deque<int>d2(d1.begin(), d1.end());
	PrintDeque(d2);
	//n个值
	deque<int>d3(10, 100);
	PrintDeque(d3);
	//拷贝构造
	deque<int>d4(d3);
	PrintDeque(d4);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.5.3deque赋值操作

#include <iostream>
using namespace std;
#include<deque>
void PrintDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)//加入const防止修改数据,这里是只读
	{
		cout << *it << ' ';
	}
	cout << endl;
}
void test1()
{
	deque<int>d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	PrintDeque(d1);
	//= 赋值
	deque<int>d2;
	d2 = d1;
	PrintDeque(d2);
	//assign区间
	deque<int>d3;
	d3.assign(d1.begin(), d1.end());
	PrintDeque(d3);
	//assign n个值
	deque<int>d4;
	d4.assign(10, 100);
	PrintDeque(d4);

}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.5.4deque大小操作

#include <iostream>
using namespace std;
#include<deque>
void PrintDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)//加入const防止修改数据,这里是只读
	{
		cout << *it << ' ';
	}
	cout << endl;
}
void test1()
{
	deque<int>d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	PrintDeque(d1);
	if (d1.empty())
	{
		cout << "容器为空" << endl;
	}
	else
	{
		cout << "容器不为空" << endl;
		cout << d1.size() << endl;
	}
	//重新指定大小  放大 默认填充
	d1.resize(15);
	PrintDeque(d1);
	//重新指定大小  放大 填充 1
	d1.resize(17, 1);
	PrintDeque(d1);
	//重新指定大小  缩小 截取数据
	d1.resize(10);
	PrintDeque(d1);

}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.5.5deque插入和和删除

#include <iostream>
using namespace std;
#include<deque>
void PrintDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)//加入const防止修改数据,这里是只读
	{
		cout << *it << ' ';
	}
	cout << endl;
}
//两端操作
void test1()
{
	deque<int>d1;
	//尾插法
	d1.push_back(10);
	d1.push_back(20);
	//头插法
	d1.push_front(100);
	d1.push_front(200);
	PrintDeque(d1);
	//尾删法
	d1.pop_back();
	PrintDeque(d1);
	//头删法
	d1.pop_front();
	PrintDeque(d1);
}
//插入
void test2()
{
	deque<int>d1;
	d1.push_back(10);
	d1.push_back(20);
	d1.push_front(100);
	d1.push_front(200);
	PrintDeque(d1);
	//在迭代器 插入 单值
	d1.insert(d1.begin(), 1000);
	PrintDeque(d1);
	//在迭代器 插入 多值
	d1.insert(d1.begin(),2, 10000);
	PrintDeque(d1);
	//在迭代器区间位置 插入 多值
	deque<int>d2;
	d2.push_back(1);
	d2.push_back(2);
	d2.push_back(3);
	d1.insert(d1.begin(),d2.begin(),d2.end() );
	PrintDeque(d1);
}
//删除
void test3()
{
	deque<int>d1;
	d1.push_back(10);
	d1.push_back(20);
	d1.push_front(100);
	d1.push_front(200);
	PrintDeque(d1);
	//删除 第一个
	d1.erase(d1.begin());
	PrintDeque(d1);
	//删除第二个
	deque<int>::iterator it = d1.begin();
	it++;
	d1.erase(it);
	PrintDeque(d1);
	//按区间删除
	d1.erase(d1.begin(), d1.end());
	PrintDeque(d1);
	//清空
	d1.clear();
	PrintDeque(d1);

}
int main()
{
	//test1();
	//test2();
	test3();
	system("pause");
	return 0;
}

10.5.6deque数据读写

#include <iostream>
using namespace std;
#include<deque>
void PrintDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)//加入const防止修改数据,这里是只读
	{
		cout << *it << ' ';
	}
	cout << endl;
}
//两端操作
void test1()
{
	deque<int>d1;
	//尾插法
	d1.push_back(10);
	d1.push_back(20);
	d1.push_back(30);
	//头插法
	d1.push_front(100);
	d1.push_front(200);
	d1.push_front(300);
	//通过 【】访问数据
	for (int i = 0; i < d1.size(); i++)
	{
		cout << d1[i] << ' ';
	}
	cout << endl;
	//通过 at访问
	for (int i = 0; i < d1.size(); i++)
	{
		cout << d1.at(i) << ' ';
	}
	cout << endl;
	//访问头,尾
	cout << "第一个元素" << d1.front() << endl;
	cout << "最后个元素" << d1.back() << endl;
}



int main()
{
	test1();

	system("pause");
	return 0;
}

10.5.7deque排序

#include <iostream>
using namespace std;
#include<deque>
#include<algorithm>
void PrintDeque(const deque<int>& d)
{
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)//加入const防止修改数据,这里是只读
	{
		cout << *it << ' ';
	}
	cout << endl;
}
//两端操作
void test1()
{
	deque<int>d1;
	//尾插法
	d1.push_back(10);
	d1.push_back(20);
	d1.push_back(30);
	//头插法
	d1.push_front(100);
	d1.push_front(200);
	d1.push_front(300);
	PrintDeque(d1);
	//sort排序规则,从小到大。对于支持随机访问迭代器的容器,也可以sort排序
	sort(d1.begin(), d1.end());
	PrintDeque(d1);

}



int main()
{
	test1();

	system("pause");
	return 0;
}

10.6stack容器

10.6.1stack基本概念

10.6.2stack常用接口

#include <iostream>
using namespace std;
#include <stack>

void test1()
{
	stack<int>s;
	//入栈
	s.push(10);
	s.push(20);
	s.push(30);
	s.push(40);
	//只要栈不为空,就查看栈顶,并且执行出栈
	while (!s.empty())
	{
		//查看栈顶元素
		cout << s.top() << endl;
		//出栈
		s.pop();
	}
	cout <<"栈的大小"<< s.size() << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.7queue容器

10.7.1queue基本概念

10.7.2queue常用接口

#include <iostream>
using namespace std;
#include<queue>
class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;

	}
	string m_Name;
	int m_Age;

};

void test1()
{
	//创建队列
	queue<Person>q;
	//准备数据
	Person p1("唐僧", 40);
	Person p2("孙悟空", 10);
	Person p3("猪八戒", 20);
	Person p4("沙参", 30);
	//入队
	q.push(p1);
	q.push(p2);
	q.push(p3);
	q.push(p4);
	cout << q.size();
	//判断只要队列不为空,查看队头,队尾,出队
	while (!q.empty())
	{
		//查看队头
		cout << q.front().m_Name << ' ' << q.front().m_Age << endl;
		//查看队尾
		cout << q.back().m_Name << ' ' << q.back().m_Age << endl;
		//出队
		q.pop();
	}
	cout << q.size();
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.8list容器

10.8.1list基本概念

10.8.2list构造函数

#include <iostream>
using namespace std;
#include<list>

void PrintList(const list<int >& l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	//默认构造
	list<int >l;
	//添加数据
	l.push_back(1);
	l.push_back(2);
	l.push_back(3);
	l.push_back(4);
	PrintList(l);
	//区间构造
	list<int>l2(l.begin(), l.end());
	PrintList(l2);
	//多值构造
	list<int>l3(10,100);
	PrintList(l3);
	//拷贝构造
	list<int>l4(l3);
	PrintList(l4);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.8.3list赋值和操作

#include <iostream>
using namespace std;
#include<list>

void PrintList(const list<int >& l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	//默认构造
	list<int >l1;
	//添加数据
	l1.push_back(1);
	l1.push_back(2);
	l1.push_back(3);
	l1.push_back(4);
	PrintList(l1);
	//赋值 =
	list<int>l2;
	l2 = l1;
	PrintList(l2);
	//赋值 assign区间
	list<int>l3;
	l3.assign(l2.begin(), l2.end());
	PrintList(l3);
	//赋值 assign多值
	list<int>l4;
	l4.assign(10,100);
	PrintList(l4);
	//交换
	list<int>l5;
	l5.assign(10, 10);
	PrintList(l5);
	l4.swap(l5);
	PrintList(l4);
	PrintList(l5);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.8.4list大小操作

#include <iostream>
using namespace std;
#include<list>

void PrintList(const list<int >& l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	//默认构造
	list<int >l1;
	//添加数据
	l1.push_back(1);
	l1.push_back(2);
	l1.push_back(3);
	l1.push_back(4);
	PrintList(l1);
	//判断容器是否为空
	if (l1.empty())
	{
		cout << "容器为空" << endl;
	}
	else
	{
		cout << "容器不为空" << endl;
		cout << "l1的元素个数:" << l1.size() << endl;
	}
	//重新指定大小 默认补值
	l1.resize(10);
	PrintList(l1);
	//重新指定大小 自己缺点
	l1.resize(12,100);
	PrintList(l1);
	//重新指定大小 缩小
	l1.resize(3);
	PrintList(l1);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.8.5list插入和删除

#include <iostream>
using namespace std;
#include<list>

void PrintList(const list<int >& l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	//默认构造
	list<int >l1;
	//添加数据	//尾插法
	l1.push_back(1);
	l1.push_back(2);
	l1.push_back(3);
	//头插法
	l1.push_front(10);
	l1.push_front(20);
	l1.push_front(30);
	PrintList(l1);
	//尾删法
	l1.pop_back();
	//头删法
	l1.pop_front();
	PrintList(l1);
	//insert插入
	l1.insert(l1.begin(), 100);
	PrintList(l1);
	//迭代器插
	list<int>::iterator it = l1.begin();
	l1.insert(it++, 200);
	PrintList(l1);
	//迭代器删除
	it = l1.begin();
	l1.erase(it);
	PrintList(l1);
	//移除 指定数据
	l1.push_back(10000);
	l1.push_front(10000);
	PrintList(l1);
	l1.remove(10000);
	PrintList(l1);
	//清空
	l1.clear();
	PrintList(l1);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.8.6list数据存取

#include <iostream>
using namespace std;
#include<list>
void PrintList(const list<int >& l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
void test1()
{
	//默认构造
	list<int >l1;
	//添加数据	//尾插法
	l1.push_back(1);
	l1.push_back(2);
	l1.push_back(3);
	//头插法
	l1.push_front(10);
	l1.push_front(20);
	l1.push_front(30);
	PrintList(l1);
	//不能用 l1【0】下标访问,不能用l1.at(0)访问.因为list不是连续线性空间存储数据
	cout << l1.front() << endl;
	cout << l1.back() << endl;
	//验证迭代器不是随机访问
	list<int>::iterator it = l1.begin();
	//it = it + 1;错误
	//it++//正确
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.8.7list反转和排序

#include <iostream>
using namespace std;
#include<list>
#include<algorithm>
void PrintList(const list<int >& l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
bool MyCompare(int v1, int v2)
{
	//降序 就让第一个数 大于 第二个数
	return v1 > v2;
}
void test1()
{
	//默认构造
	list<int >l1;
	//添加数据	//尾插法
	l1.push_back(1);
	l1.push_back(3);
	l1.push_back(2);
	//头插法
	l1.push_front(10);
	l1.push_front(200);
	l1.push_front(30);
	PrintList(l1);
	//反转
	l1.reverse();
	PrintList(l1);
	//排序
	//sort(l1.begin(), l1.end());错误,因为list容器不支持随机访问,所以不能用标准算法
	//不支持随机访问迭代器的内部,会提供一些算法
	l1.sort();//升序
	PrintList(l1);
	l1.sort(MyCompare);//降序
	PrintList(l1);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.9set和multiset容器

10.9.1set基本概念

10.9.2set构造和赋值

#include <iostream>
using namespace std;
#include <set>

void PrintSet(set<int>&s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	set<int>s1;
	//插入数据,只有insert
	//这里插入的是无序排序。但输出是有序
	s1.insert(10);
	s1.insert(20);
	s1.insert(70);
	s1.insert(40);
	s1.insert(20);
	//遍历容器
	//set容器不允许插入重复值
	PrintSet(s1);
	set<int>s2(s1);
	PrintSet(s2);
	//赋值
	set<int>s3;
	s3 = s2;
	PrintSet(s3);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.9.3set大小和交换

#include <iostream>
using namespace std;
#include <set>

void PrintSet(set<int>& s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	set<int>s1;
	//插入数据,只有insert
	//这里插入的是无序排序。但输出是有序
	s1.insert(10);
	s1.insert(20);
	s1.insert(70);
	s1.insert(40);
	s1.insert(20);
	//遍历容器
	//set容器不允许插入重复值
	PrintSet(s1);
	//判断容器是否为空
	if (s1.empty())
	{
		cout << "容器为空" << endl;
	}
	else
	{
		cout << "容器不为空" << endl;
		cout << s1.size() << endl;
	}
	//交换
	set<int>s2;
	s2.insert(1);
	s2.insert(2);
	s2.insert(7);
	s2.insert(4);
	s2.insert(2);
	PrintSet(s1);
	PrintSet(s2);
	s2.swap(s1);
	PrintSet(s1);
	PrintSet(s2);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.9.4set插入和删除

#include <iostream>
using namespace std;
#include <set>

void PrintSet(set<int>& s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	set<int>s1;
	//插入数据,只有insert
	//这里插入的是无序排序。但输出是有序
	s1.insert(10);
	s1.insert(20);
	s1.insert(70);
	s1.insert(40);
	s1.insert(20);
	s1.insert(80);
	s1.insert(180);
	//遍历容器
	//set容器不允许插入重复值
	PrintSet(s1);
	//删除 迭代器
	s1.erase(s1.begin());
	PrintSet(s1);
	//删除 迭代器任意位置
	set<int>::iterator it = s1.begin();
	s1.erase(++it);
	PrintSet(s1);
	//删除具体数
	s1.erase(80);
	PrintSet(s1);
	//清空
	s1.erase(s1.begin(), s1.end());
	PrintSet(s1);
	//清空
	s1.clear();
	PrintSet(s1);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.9.5查找和统计

#include <iostream>
using namespace std;
#include <set>

void PrintSet(set<int>& s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	set<int>s1;
	//插入数据,只有insert
	//这里插入的是无序排序。但输出是有序
	s1.insert(10);
	s1.insert(20);
	s1.insert(70);
	s1.insert(40);
	s1.insert(20);
	s1.insert(80);
	s1.insert(180);
	//遍历容器
	//set容器不允许插入重复值
	PrintSet(s1);
	//查找
	set<int>::iterator it = s1.find(20);
	if (it != s1.end())
	{
		cout << "找到了!"<<' ' << *it << endl;
	}
	else
	{
		cout << "没找到" << endl;
	}
	//统计
	int num=s1.count(20);
	cout << "20个数:" << num << endl;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.9.6set和multiset区别

#include <iostream>
using namespace std;
#include <set>

void PrintSet(multiset<int>& s)
{
	for (multiset<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	set<int>s1;
	//插入数据,只有insert
	//这里插入的是无序排序。但输出是有序
	pair<set<int>::iterator ,bool> ret =s1.insert(10);
	if (ret.second)
	{
		cout << "第一次插入成功" << endl;
	}
	else
	{
		cout << "第一次插入失败" << endl;
	}
	ret = s1.insert(10);
	if (ret.second)
	{
		cout << "第2次插入成功" << endl;
	}
	else
	{
		cout << "第2次插入失败" << endl;
	}
	multiset<int>ms;//允许插入重复
	ms.insert(20);
	ms.insert(20);
	ms.insert(10);
	PrintSet(ms);
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.9.7pair队组创建

#include <iostream>
using namespace std;
#include <set>

void PrintSet(multiset<int>& s)
{
	for (multiset<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

void test1()
{
	//第一种
	pair<string, int> p1("刘家森", 22);
	cout << p1.first << ' ' << p1.second << endl;
	//第二种
	pair<string, int>p2 = make_pair("罗灿灿", 21);
	cout << p2.first << ' ' << p2.second << endl;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.9.8set容器内置数据排序

#include <iostream>
using namespace std;
#include <set>

void PrintSet(set<int>&s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}


class MyCompare
{
public:
	bool operator()(int v1,int v2)const
	{
		return v1 > v2;
	}
};

void test1()
{
	set<int>s1;
	//插入数据,只有insert
	//这里插入的是无序排序。但输出是有序
	s1.insert(10);
	s1.insert(20);
	s1.insert(70);
	s1.insert(40);
	s1.insert(20);
	PrintSet(s1);//默认为升序
	//指定排序规则为降序
	set<int, MyCompare>s2;
	//插入数据,只有insert
	//这里插入的是无序排序。但输出是有序
	s2.insert(10);
	s2.insert(20);
	s2.insert(70);
	s2.insert(40);
	for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.9.9set容器自定义数据排序

#include <iostream>
using namespace std;
#include <set>

void PrintSet(set<int>& s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}
class Person
{
public:
	Person(string name, int age) 
	{
		m_Name = name;
		m_Age = age;
	}
	string m_Name;
	int m_Age;
};

class MyCompare
{
public:
	bool operator()(const Person &p1, const Person &p2) const
	{
		return p1.m_Age > p2.m_Age;
	}
};


void test1()
{
	set<Person, MyCompare>s;
	Person p1("刘备", 24);
	Person p2("关羽", 28);
	Person p3("张飞", 25);
	Person p4("赵云", 21);
	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);
	for (set<Person,MyCompare>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << it->m_Name << ' ' << it->m_Age << endl;
	}

}
int main()
{
	test1();
	system("pause");
	return 0;
}

10.10map和multimap容器

10.10.1map基本概念

10.10.2map构造和赋值

#include <iostream>
using namespace std;
#include<map>

void PrintMap(map<int, int>&m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << (*it).first << ' ' << it->second << endl;
	}
	cout << endl;
}

void test1()
{
	//默认构造
	map<int, int>m;
	//赋值 insert
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(4, 40));
	PrintMap(m);//会自动排序会升序
	//拷贝构造
	map<int, int>m2(m);
	PrintMap(m2);
	//赋值 =
	map<int, int>m3;
	m3 = m2;
	PrintMap(m3);
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.10.3map大小和交换

#include <iostream>
using namespace std;
#include<map>

void PrintMap(map<int, int>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << (*it).first << ' ' << it->second << endl;
	}
	cout << endl;
}

void test1()
{
	//默认构造
	map<int, int>m;
	//赋值 insert
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(4, 40));
	//PrintMap(m);//会自动排序会升序
	//判断容器是否为空
	if (m.empty())
	{
		cout << "内容为空" << endl;
	}
	else
	{
		cout << "内容不为空" << endl;
		cout << m.size() << endl;
	}
	//交换
	map<int, int>m2;
	m2.insert(pair<int, int>(1, 100));
	m2.insert(pair<int, int>(3, 300));
	m2.insert(pair<int, int>(2, 200));
	m2.insert(pair<int, int>(4, 400));
	PrintMap(m);
	PrintMap(m2);
	//交换
	m2.swap(m);
	PrintMap(m);
	PrintMap(m2);
}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.10.4map插入和删除

#include <iostream>
using namespace std;
#include<map>

void PrintMap(map<int, int>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << (*it).first << ' ' << it->second << endl;
	}
	cout << endl;
}

void test1()
{
	//默认构造
	map<int, int>m;
	//插入第一种 insert
	m.insert(pair<int, int>(1, 10));
	//插入第2种 insert
	m.insert(make_pair(2, 20));
	//插入第3种 insert
	m.insert(map<int, int>::value_type(4, 30));
	//插入第4种 insert  不推荐!!因为会容易误插。可以利用key访问value
	m[3] = 40;
	cout << m[2] << endl;
	PrintMap(m);//会自动排序会升序
	//删除 迭代器
	m.erase(m.begin());
	PrintMap(m);
	//删除 指定元素
	m.erase(3);
	PrintMap(m);
	//删除 区间
	m.erase(m.begin(), m.end());
	PrintMap(m);
	//清空
	m.clear();
	PrintMap(m);

}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.10.5map查找和统计

#include <iostream>
using namespace std;
#include<map>

void PrintMap(map<int, int>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << (*it).first << ' ' << it->second << endl;
	}
	cout << endl;
}

void test1()
{
	//默认构造
	map<int, int>m;
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(3, 20));
	m.insert(pair<int, int>(3, 200));
	m.insert(pair<int, int>(2, 30));
	m.insert(pair<int, int>(4, 40));

	//查找
	map<int, int>::iterator pos = m.find(2);
	if (pos != m.end())
	{
		cout << "找到了:" << (*pos).first << ' ' << pos->second << endl;
	}
	else
	{
		cout << "没找到" << endl;
	}
	//统计
	int num = m.count(3);//不允许插入 重复值,返回情况为 1 和 0.但是multimap可以
	cout << num << endl;


}

int main()
{
	test1();
	system("pause");
	return 0;
}

10.10.6map容器内置数据排序

#include <iostream>
using namespace std;
#include<map>

class MyCompare
{
public:
	bool operator()(int v1, int v2)const
	{
		return v1 > v2;
	}

};

void test1()
{
	map<int, int,MyCompare>m;
	m.insert(make_pair(1, 10));
	m.insert(pair<int,int>(2, 30));
	m.insert(make_pair(3, 100));
	m.insert(make_pair(4, 110));
	//输出
	for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << (*it).first << ' ' << it->second << endl;
	}
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}

11.1STL-函数对象

11.1.1函数对象基本概念

11.1.2函数对象使用

#include <iostream>
using namespace std;


//1.函数对象(仿函数)在使用时,可以像普通函数那样调用,可以有参数,也可以有返回值
class MyAdd
{
public:
	int operator()(int v1, int v2)
	{
		return v1 + v2;
	}
};
//2.函数对象超出普通函数的概念,可以拥有自己的状态
class MyPrint
{
public:
	MyPrint()
	{
		count = 0;
	}
	void operator()(string test)
	{
		cout << test << endl;
		count++;
	}

	int count;//内部自己状态记录
};


void test1()
{
	MyAdd myadd;
	cout << myadd(10, 10) << endl;
}
void test2()
{
	MyPrint myprint;
	myprint("hello world");
	myprint("hello world");
	cout << myprint.count << endl;
}
void doPrint(MyPrint& mp, string test)
{
	mp(test);
}
//3.函数对象可以组为参数进行传递
void test3()
{
	MyPrint myPrint;
	doPrint(myPrint, "C++");
}
int main()
{
	test1();
	test2();
	test3();
	system("pause");
	return 0;
}

11.2谓词

11.2.1谓词概念

11.2.2一元谓词

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>

class GreatFive
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};
void test1()
{
	vector<int>v;
	GreatFive greatfive;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	//查找容器中有没有大于5的数
	//GreatFive()是匿名对象
		//find_if(v.begin(), v.end(), greatfive);//正确
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreatFive());
	if (it == v.end())
	{
		cout << "没找到" << endl;
	}
	else
	{
		cout << "找到了:" <<*it<< endl;
	}

}

int main()
{
	test1();
	system("pause");
	return 0;
}

11.2.3二元谓词

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>

class GreatFive
{
public:
	bool operator()(int v1,int v2)
	{
		return v1 > v2;
	}
};
void test1()
{
	vector<int>v;
	GreatFive greatfive;
	v.push_back(1);
	v.push_back(3);
	v.push_back(2);
	v.push_back(5);
	v.push_back(4);
	sort(v.begin(),v.end());
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
	//使用函数对象 改变算法,实现降序排列
	sort(v.begin(), v.end(), GreatFive());
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

11.3内建函数对象

11.3.1内建函数对象意义

11.3.2算术仿函数

#include <iostream>
using namespace std;
#include<functional>
void test1()
{
	//neagte 一元运算(取反)
	negate<int>n;
	cout<<n(50)<<endl;
	//plus 二元运算(加法)
	plus<int>m;
	cout << m(10, 20) << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

11.3.3关系仿函数

#include <iostream>
using namespace std;
#include<functional>
#include<vector>
#include<algorithm>
class MyCompare
{
public:
	bool operator()(int v1, int v2)
	{
		return v1 > v2;
	}
};
void test1()
{
	vector<int>v;
	v.push_back(1);
	v.push_back(5);
	v.push_back(3);
	v.push_back(2);
	v.push_back(4);
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
	//降序 自己写仿函数
	//sort(v.begin(), v.end(), MyCompare());
	//系统自带仿函数 greater
	sort(v.begin(), v.end(), greater<int>());
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

11.3.4逻辑仿函数

#include <iostream>
using namespace std;
#include<functional>
#include<algorithm>
#include<vector>
void test1()
{
	//逻辑非 logical_not
	vector<bool>v;
	v.push_back(true);
	v.push_back(false);
	v.push_back(true);
	v.push_back(false);
	for (vector<bool>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
	//利用逻辑非 将上面容器 搬到v2中,并执行取反
	vector<bool>v2;
	v2.resize(v.size());
	transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());
	for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

12STL常用算法

12.1常用算法基本概念

12.2常用遍历算法

12.2.1for_each

#include <iostream>
using namespace std;
#include<algorithm>
#include<vector>

//普通函数
void print1(int val)
{
	cout << val << ' ';
}
class prin2
{
public:
	void operator()(int val)
	{
		cout << val << ' ';
	}
};
void test1()
{
	vector<int>v;
	v.push_back(1);
	v.push_back(3);
	v.push_back(5);
	v.push_back(2);
	v.push_back(4);
	//方法一 普通函数 放函数名字
	for_each(v.begin(), v.end(), print1);
	cout << endl;
	//方法二 仿函数  放匿名对象
	for_each(v.begin(), v.end(), prin2());
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}

12.2.2transform

#include <iostream>
using namespace std;
#include<algorithm>
#include<vector>



class Transform
{
public:
	int operator()(int val)
	{
		return val+100;
	}
};
class Print
{
public:
	void operator()(int val)
	{
		cout<<val<<' ';
	}
};
void test1()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	
	vector<int>vTarget;//目标容器
	vTarget.resize(v.size());
	transform(v.begin(), v.end(), vTarget.begin(), Transform());
	for_each(vTarget.begin(), vTarget.end(), Print());
	cout << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}

12.3常用查找算法

12.3.1find

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>
void test1()
{
	//查找 内置数据类型
	vector<int>v;
	for(int i=0;i<10;i++)
	{ 
		v.push_back(i);
	}
	//查找有没有 5
	vector<int>::iterator it=find(v.begin(), v.end(), 5);
	if (it == v.end())
	{
		cout << "没有找到"<< endl;
	}
	else
	{
		cout << "找到了:" << *it << endl;
	}
}
class Person 
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}
	//重载 == 才能实现 Person比较
	bool operator==(const Person &p1)
	{
		if (this->m_Name == p1.m_Name && this->m_Age == p1.m_Age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	string m_Name;
	int m_Age;
};
void test2()
{
	//查找 自定义数据类型
	vector<Person>v;
	//创建数据
	Person p1("aa",10);
	Person p2("bb", 20);
	Person p3("cc", 30);
	Person p4("dd", 40);
	//放入容器
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	//查找 y有没有 pp这个人在容器中
	Person pp("dd", 40);
	vector<Person>::iterator it = find(v.begin(), v.end(), pp);
	if (it == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了:" << ( * it).m_Name<<' '<<it->m_Age << endl;
	}
}
int main()
{
	test2();
	system("pause");
	return 0;
}

12.3.2find_if

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>

class GreatFive
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}

};
void test1()
{
	//查找 内置数据类型
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	//查找有没有 5
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreatFive());
	if (it == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了:" << *it << endl;
	}
}
class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}
	string m_Name;
	int m_Age;
};
class Greta20
{
public:
	bool operator()(const Person& p1)
	{
		return p1.m_Age > 20;
	}
};
void test2()
{
	//查找 自定义数据类型
	vector<Person>v;
	//创建数据
	Person p1("aa", 10);
	Person p2("bb", 20);
	Person p3("cc", 30);
	Person p4("dd", 40);
	//放入容器
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	//查找 y有没有 pp这个人在容器中
	Person pp("dd", 40);
	vector<Person>::iterator it = find_if(v.begin(), v.end(), Greta20());
	if (it == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了:" << (*it).m_Name << ' ' << it->m_Age << endl;
	}
}
int main()
{
	test2();
	system("pause");
	return 0;
}

12.3.3adjacent_find

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>


void test1()
{
	vector<int>v;
	v.push_back(0);
	v.push_back(2);
	v.push_back(0);
	v.push_back(3);
	v.push_back(1);
	v.push_back(4);
	v.push_back(3);
	v.push_back(3);
	vector<int>::iterator it = adjacent_find(v.begin(),v.end());
	if (it == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了:" << (*it) << endl;
	}
}


int main()
{
	test1();
	system("pause");
	return 0;
}

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>


void test1()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	bool ret = binary_search(v.begin(), v.end(), 9);
	if (ret )
	{
		cout << "找到了" << endl;
	}
	else
	{
		cout << "没有找到:"  << endl;
	}

}

int main()
{
	test1();
	system("pause");
	return 0;
}

12.3.5count

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>


void test1()
{
	//内置数据
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	v.push_back(1);
	v.push_back(1);
	int ret = count(v.begin(), v.end(), 1);
	cout << ret << endl;
}

class Person
{
public:
	Person(string name,int age)
	{
		m_name = name;
		m_age = age;
	}
	bool operator==(const Person& p)
	{
		if (this->m_age == p.m_age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	string m_name;
	int m_age;
};
void test2()
{
	//	自定义数据类型
	vector<Person>v;
	Person p1("刘备", 72);
	Person p2("关羽", 32);	
	Person p3("张飞", 42);
	Person p4("曹操", 72);
	Person p5("赵云", 62);
	Person pp("诸葛亮", 72);
	//将人员插入容器
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);
	int num = count(v.begin(), v.end(), pp);
	cout << "和诸葛亮年纪一样的有:" << num << endl;
}
int main()
{
	test2();
	system("pause");
	return 0;
}

12.3.6count_if

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>

class Greater5
{
public:
	bool operator()(int v)
	{
		return v > 5;
	}
};

void test1()
{
	//内置数据
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	v.push_back(20);
	v.push_back(1);
	int ret = count_if(v.begin(), v.end(), Greater5());
	cout << ret << endl;
}

class Person
{
public:
	Person(string name, int age)
	{
		m_name = name;
		m_age = age;
	}
	
	string m_name;
	int m_age;
};
class Greater50
{
public:
	bool operator()(const Person &p)
	{
		if (p.m_age > 52)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};
void test2()
{
	//	自定义数据类型
	vector<Person>v;
	Person p1("刘备", 72);
	Person p2("关羽", 32);
	Person p3("张飞", 42);
	Person p4("曹操", 72);
	Person p5("赵云", 62);
	//将人员插入容器
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);
	int num = count_if(v.begin(), v.end(), Greater50());
	cout << "大于52的有:" << num << endl;
}
int main()
{
	test2();
	system("pause");
	return 0;
}

12.4常用排序算法

12.4.1sort

#include <iostream>
using namespace std;
#include<vector >
#include<algorithm>
#include<functional>
void MyPrint(int v)
{
	cout << v << ' ';
}
void test1()
{
	vector<int>v;
	v.push_back(1);
	v.push_back(3);
	v.push_back(5);
	v.push_back(2);
	v.push_back(4);
	//利用sort升序
	sort(v.begin(), v.end());
	for_each(v.begin(), v.end(), MyPrint);
	cout << endl;
	//降序
	sort(v.begin(), v.end(),greater<int>());
	for_each(v.begin(), v.end(), MyPrint);
	cout << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}
//928

12.4.2random_shuffle

#include <iostream>
using namespace std;
#include<vector >
#include<algorithm>
#include<functional>
#include<ctime>
void MyPrint(int v)
{
	cout << v << ' ';
}
void test1()
{
	vector<int>v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	//利用洗牌算法打乱顺序
	random_shuffle(v.begin(), v.end());

	for_each(v.begin(), v.end(), MyPrint);
	cout << endl;
}

int main()
{
	srand((unsigned int)time(NULL));
	test1();
	system("pause");
	return 0;
}
//928

12.4.3merge

#include <iostream>
using namespace std;
#include<vector >
#include<algorithm>
#include<functional>
void MyPrint(int v)
{
	cout << v << ' ';
}
void test1()
{
	vector<int>v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	vector<int>v1;
	v1.push_back(4);
	v1.push_back(5);
	v1.push_back(6);
	v1.push_back(7);
	v1.push_back(8);
	//合并
	vector<int>v2;
	//目标容器分配内存
	v2.resize(v.size()+v1.size());
	merge(v.begin(), v.end(), v1.begin(), v1.end(), v2.begin());
	for_each(v2.begin(), v2.end(), MyPrint);
	cout << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}
//928

12.4.5reverse

#include <iostream>
using namespace std;
#include<vector >
#include<algorithm>
#include<functional>
void MyPrint(int v)
{
	cout << v << ' ';
}
void test1()
{
	vector<int>v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	//翻转
	reverse(v.begin(), v.end());
	for_each(v.begin(), v.end(), MyPrint);
	cout << endl;
}

int main()
{
	test1();
	system("pause");
	return 0;
}
//928

12.5常用拷贝和替换算法

12.5.1copy

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>


void MyPrin(int v)
{
	cout << v << ' ';
}
void test1()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	vector<int>v2;
	v2.resize(v.size());
	//复制 v 到 v2
	copy(v.begin(), v.end(), v2.begin());
	for_each(v2.begin(), v2.end(), MyPrin);
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}

12.5.2replace

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>

//仿函数
class MyPrint
{
public:
	void operator()(int v)
	{
		cout << v << ' ';
	}
};
void test1()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), MyPrint());
	cout << endl;
	//把 v 中的 9 替换为 90
	replace(v.begin(), v.end(), 9, 90);
	for_each(v.begin(), v.end(), MyPrint());
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}

12.5.3replace_if

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>
//谓词
class Greater5
{
public:
	bool operator()(int v)
	{
		return v >= 5;
	}
};

//仿函数
class MyPrint
{
public:
	void operator()(int v)
	{
		cout << v << ' ';
	}
};
void test1()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), MyPrint());
	cout << endl;
	//把 v 中的 大于5的 都替换为 50
	replace_if(v.begin(), v.end(), Greater5(), 50);
	for_each(v.begin(), v.end(), MyPrint());
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}

12.5.4swap

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>


void MyPrin(int v)
{
	cout << v << ' ';
}
void test1()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	vector<int>v2;
	for (int i = 10; i < 20; i++)
	{
		v2.push_back(i);
	}
	for_each(v.begin(), v.end(), MyPrin);
	cout << endl;
	for_each(v2.begin(), v2.end(), MyPrin);
	cout << endl;
	//交换 v 和 v2
	swap(v, v2);
	for_each(v.begin(), v.end(), MyPrin);
	cout << endl;
	for_each(v2.begin(), v2.end(), MyPrin);
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}

12.6常用算术生成算法

12.6.1accumulate

#include <iostream>
using namespace std;
#include<numeric>
#include<vector>

void test1()
{
	vector<int>v;
	for (int i = 0; i <= 100; i++)
	{
		v.push_back(i);
	}
	//计算容器和  0为返回的起始值,写0则为sum=sum+0  写10就为 sum=sum+10
	int sum=accumulate(v.begin(), v.end(),0);
	cout << sum << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}
//928

12.6.2fill

#include <iostream>
using namespace std;
#include<numeric>
#include<vector>
#include<algorithm>


void MyPrint(int v)
{
	cout << v << ' ';
}
void test1()
{
	vector<int>v;
	v.resize(10);//默认填充为 0
	//重新填充容器  把默认值0 全部填充为 100 
	fill(v.begin(), v.end(), 100);
	for_each(v.begin(), v.end(),MyPrint);
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}
//928

12.7常用集合算法

12.7.1set_intersection

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>


class MyPrint
{
public:
	void operator()(int v)
	{
		cout<< v<<' ';
	}
};
void test1()
{
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(i + 5);
	}
	//目标容器需要提前开辟内存   空间取小容器size
	vector<int>vTarget;
	vTarget.resize(min(v1.size(), v2.size()));
	//求交集 得到交集位置迭代器位置
	vector<int>::iterator itEnd =set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	for_each(vTarget.begin(), itEnd, MyPrint());
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}

12.7.2set_unin

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>


class MyPrint
{
public:
	void operator()(int v)
	{
		cout << v << ' ';
	}
};
void test1()
{
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(i + 5);
	}
	//目标容器需要提前开辟内存   空间容器和
	vector<int>vTarget;
	vTarget.resize((v1.size()+v2.size()));
	//求并集 得到并集位置迭代器位置
	vector<int>::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	for_each(vTarget.begin(), itEnd, MyPrint());
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}

12.7.3set_difference

#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>


class MyPrint
{
public:
	void operator()(int v)
	{
		cout << v << ' ';
	}
};
void test1()
{
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(i + 5);
	}
	//目标容器需要提前开辟内存   空间容器和
	vector<int>vTarget;
	vTarget.resize(max(v1.size(),v2.size()));
	//求差集 得到差集位置迭代器位置
	vector<int>::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	cout << "v1和v2差集" << endl;//v2和v1差集不一样
	for_each(vTarget.begin(), itEnd, MyPrint());
	cout << endl;

}

int main()
{
	test1();
	system("pause");
	return 0;
}

1丶冒泡排序

	for (int i = 0; i < 9; i++)
	{
		//进行循环对比 次数为:元素个数-排序轮数-1
		for (int j = 0; j < 9 - i - 1; j++)
		{
			//如果第一个大于第二个,则交换
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}

	}

2丶选择排序

for (int i = 0; i < m_EmpNum; i++)
		{
			int minOrMax = i;//声明最小值 或 最大值
			for (int j = i + 1; j < this->m_EmpNum; j++)
			{
				if (select == 1)
				{
					if (this->m_EmpArray[minOrMax]->m_id> this->m_EmpArray[j]->m_id)
					{
						minOrMax = j;
					}
				}
				else//降序
				{
					if (this->m_EmpArray[minOrMax]->m_id < this->m_EmpArray[j]->m_id)
					{
						minOrMax = j;
					}
				}
			}
			//判断一开始认定的 最小值或最大值 是不是计算的最小值或最大值,如果不是,交换数据
			if (i != minOrMax)
			{
				Worker* temp = this->m_EmpArray[i];
				this->m_EmpArray[i] = this->m_EmpArray[minOrMax];
				this->m_EmpArray[minOrMax] = temp;
			}
		}
举报

相关推荐

0 条评论