前言
为什么写C++复习笔记?脑子不好使,今天学明天忘。
为什么一堆代码?代码是敲出来的,不是看出来的。里面的代码都运行过,萌新跟着敲就完事了,也有注释辅助理解。至于有基础的,代码就这么点,不难看懂。
1.变量大小:(64位操作系统下占据内存大小)
cout << sizeof(char) << endl;//1cout << sizeof(short int) << endl;//2
cout << sizeof(int) << endl;//4
cout << sizeof(unsigned int) << endl;//4cout << sizeof(float) << endl;//4
cout << sizeof(double) << endl;//8cout << sizeof(long) << endl;//4
cout << sizeof(unsigned long) << endl;//4
cout << sizeof(long long) << endl;//8//字符转变为ASCII码:
 'a’=   97;     'b' = 98;   'c' = '99';........
 'A'  =   65;   'B' = 66;   'C' = '67';........
2.数组逆置
#include<iostream>
using namespace std;
int main() {int str[] = { 1,2,3,4,5 };int start = 0;int end = sizeof(str) / sizeof(int) - 1;while (start < end) {int temp = str[start];str[start] = str[end];str[end] = temp;start++;end--;}for (int i = 0; i < sizeof(str)/4; i++) {cout << str[i] << " ";}cout << endl;system("pause");return 0;
}3.冒泡排序
int arr[] = { 4,2,8,0,5,7,1,3,9 };
//总共排序轮数:元素个数-1;
for (int i = 0;i < 8;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;}}
}4.三目运算符:
int max(int num1, int num2) {return (num1 > num2) ? num1 : num2;
}5.二维数组注意事项
二维数组列项不能空值。
eg:
 int arr[][3]={};
6.传递
 //6.1.值传递:函数形参发生改变,不会影响实参。
 //6.2.地址传递:函数形参发生改变,实参跟着改变。
7.函数的分文件编写
 //7.1创建.h后缀名的头文件
 //7.2创建.cpp后缀名的源文件
 //7.3在头文件中写函数的声明
 //7.4在源文件中写函数的定义
 //eg:
 -------------------------------------------------------------------------------------------------
 //头文件swap.h
#include <iostream>
using namespace std;
//函数声明
void swap(int a,int b);//函数声明可以写多次,但定义只能写一次。
 -------------------------------------------------------------------------------------------------
 //源文件swap.cpp
#include "swap.h"
//函数的定义
void swap(int a,int b) {int temp = a;a = b;b = temp;cout << "a=" << a << endl;cout << "b=" << b << endl;
}
 //--------------------------------------------------------------------------------------------------
 //主源文件
#include<iostream>
#include "swap.h"
using namespace std;
int main() {int a = 19;int b = 30;swap(a, b);system("pause");return 0;
}8.指针
 //8.1指针定义:
 int a =10;
 int *p=&a;
 cout<<&a<<endl;
 cout<<p<<endl;
 //此时得到相同的内存地址
//8.2指针使用
 //通过解引用的方式来找到指针指向的内容。(指针前加*代表解引用,找到指针指向的内存中的数据)
 *p = 1000;
 cout<<a<<endl;
 cout<<*p<<endl;
 //此时得到的两个结果都为1000
//8.3指针所占内存空间
 //不管什么数据类型,在32(64)位操作系统下,指针是占4(8)个字节空间大小。
 //检测指针所占内存大小:
 int a = 10;
 int *p = &a;
 cout<<sieof(int *)<<endl;//方式一
 cout<<sizeof(p)<<endl;//方式二
//8.4空指针和野指针
 //空指针和野指针都不是我们申请的空间,因此不要访问。
 //8.4.1空指针
 //空指针:指针变量指向内存中编号为0的空间。
 //空指针的用途:初始化指针变量。
 int  *p = null;
 //空指针指向的内存是不可以访问的。(0~255之间的内存编号是系统占用的,因此不可以访问)
 //8.4.2野指针:指针变量指向非法的内存空间
 int *p = 0x0011;
 cout<<p<<endl;//此时运行会报错
//8.5const修饰指针
 //8.5.1常量指针
 //特点:指针的指向可以修改,但是指针指向的值不可以改
 const int * p = &a;
 p = &b;
 //8.5.2指针常量
 //特点:指针的指向不可以改,指针指向的值可以改。
 int * const p = &a;
 *p = 20;
 //8.5.3const既修饰指针又修饰常量
 //特点:指针的指向和指针指向的值都不可以改。
 const int * const p = &a;
//8.6利用指针访问数组中的元素。
 int arr [ ] ={1,2,3,4,5};
 int *p = arr;
 cout<<*p<<endl;//指针访问第一个元素
 p++;//使指针向后偏移4个字节
 cout<<*p<<endl;//指针访问第二个元素
//8.7用指针做函参,以修改实参的值。
 //如果不想修改实参,就用值传递;想修改,就用地址传递。
 //8.7.1地址传递
 //如果是地址传递,可以修饰实参
 int a =10;
 int b = 20;
 swap(&a,&b);
void swap(int *p1,int *p2){
      int temp = *p1;
      *p1 = * p2;
      * p2 = temp;
 }
9.结构体
 //自定义数据类型,一些类型集合组成的一个类型。
//9.1.1创建数据类型: //结构体创建的时候,struct关键字可省略,定义不行。
struct Student{//成员列表String name;//姓名int age;       //年龄int score;   //分数
};//9.1.2创建实例
 //方法一:
struct Student s1;          //结构体变量利用操作符“.”访问成员。
s1.name = "张三";
s1.age = 18;
s1.score = 88;
cout<<s1.name<<endl;//不加引号调用字符串时,要在文件开头加上#include<string>,否则会报错。
 //方法二:
struct Student s2  = {"李四",19,99};
 //方法三:
 //定义结构体时,顺便创建结构体变量。
struct Student{String name;//姓名int age;//年龄int score;//分数
}s3;
s3.name = "王五";
s3.age = 20;
s3.score = 77;//9.2结构体数组
struct Student stuArray[3] = 
{{"张三",18,100},{“李四”,28,99},{”王五“,38,66}
};//9.3结构体指针
 //9.3.1通过指针指向结构体变量
student s = {"张三",18,100};
student * p = &s;
cout<<"姓名:"<<p->name<<"年龄:"<<p->age<<"成绩:"<<p->score<<endl;//指针通过->操作符可以访问成员和成员的属性
 //9.4结构体嵌套结构体
struct student
{string name;int age;int score;
};struct teacher
{int id;string name;int age;struct student stu;
};#include<iostream>
using namespace std;
int main(){teacher t;t.id = 10000;t.name = "老王";t.age = 50;t.stu.name  ="小王";t.stu.age = 20;t.stu.score = 60;cout<<"学生名字"<<t.stu.name<<endl;return0;
}//9.5结构体做函参 //如果不想修改主函数中的数据,用值传递,否则用地址传递
struct student
{string name;int age;int score;
};struct Student s1;          //结构体变量利用操作符“.”访问成员。
s1.name = "张三";
s1.age = 18;
s1.score = 88;
printfStudent1(s1);
printfStudent2(&s1);//值传递:
void printStudent1(struct student s){cout<<"姓名"<<s.name<<endl;
}//地址传递:
void prinStudent2(struct student * p)//函数形参改为指针,可以减少内存空间,而且不会复制新的副本出来
{cout<<"姓名:"<<p->name<<endl;
}//9.6结构体中使用const:
void printStudent(const  student * stu)//加const防止函数体中的误操作
{//stu->age = 100;//操作失败,因为加了const修饰。cout<<"姓名"<<stu->name<<endl;
}//9.7结构体数组做形参
#include<iostream>
using namespace std;struct Hero {string name;int age;string sex;
};void bubbleSort(struct Hero heroArray[], int len)
{for (int i = 0; i < len - 1; i++) {for (int j = 0; j < len - i - 1; j++) {if (heroArray[j].age > heroArray[j + 1].age) {struct Hero temp = heroArray[j];heroArray[j] = heroArray[j + 1];heroArray[j + 1] = temp;}}}
}int main() {struct Hero heroArray[3] ={{"刘备",19,"男"},{"关羽",18,"男"},{"貂蝉",17,"女"}};int len = sizeof(heroArray) / sizeof(heroArray[0]);bubbleSort(heroArray, len);Hero* p = heroArray;for (int i = 0; i < len; i++) {cout << "姓名:" << p->name << "年龄:" << p->age << "成绩:" << p->sex << endl;p++;//移动指针到下一个位置}system("pause");return 0;
}10.case语句注意事项
case 3:
{       //switch语句中,case里的内容太多,如果不打括号的话,会报错cout << "请输入删除的联系人姓名:" << endl;string name;cin >> name;if (isExist(&abs, name) == -1) {cout << "查无此人" << endl;}else {cout << "找到了" << endl;}
}break;11.。。。
//每次创建源文件都要敲这玩意,保存做模板,以后就可以直接复制粘贴了。
#include<iostream>
using namespace std;void test01() {}int main() {void test01();system("pause");return 0;
}12.内存
 //12.1内存分区(变量所属区域不同,则生命周期不同)
 //代码区:存放函数体的二进制代码,由操作系统管理(共享且只读)
 //全局区:存放全局变量和静态变量以及常量(操作系统释放)
 //栈区:由编译器自动分配释放,存放函数的参数值,局部变量等(不要返回局部变量的地址)
 //堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收(分配生,释放死)
 //c++中在程序运行前分为全局区和代码区。//12.2常/变量创建:
#include<iostream>
using namespace std;int g_a = 10;//创建全局变量
const int c_g_a = 10;//创建全局常量
int main() {int a = 10;//创建局部变量static int s_a = 10;//创建静态变量cout << (int)&"字符串常量" << endl;//创建字符串常量const int c_l_a = 10;//创建局部常量return 0;
}//12.3栈区:
#include<iostream>
using namespace std;int* func() {int a = 10;//局部变量,存放在栈区,栈区的数据在函数执行完后自动释放return &a;//返回局部变量的地址
}int main() {int* p = func();//接受func函数返回值cout << *p << endl;//第一次可以打印正确的数字,是因为编译器做了保留cout << *p << endl;//第二次这个数据就不再保留了(vs2022可以)system("pause");return 0;
}//12.4堆区:
#include<iostream>
using namespace std;int* func() {//利用new关键字,可以将数据开辟到堆区//指针本质也是局部变量,放在栈上,指针保存的数据是放在堆区,从而保留数据int * p = new int(10);//new完返回开辟出来的地址return p;
}int main() {//在堆区开辟数据int* p = func();cout << *p << endl;//10cout << *p << endl;//10cout << *p << endl;//10cout << *p << endl;//10system("pause");return 0;
}
 //12.5new操作符
#include<iostream>
using namespace std;int* func() {//在堆区创建整形数据int * p = new int(10);//new返回的是该数据类型的指针return p;
}void test01() {//堆区的数据由程序员开辟,释放int* p = func();cout << *p << endl;cout << *p << endl;cout << *p << endl;//如果想释放堆区的数据,利用关键字deletedelete p;//cout<<*p<<endl;//内存已被释放,再次访问非法。
}//在堆区利用new开辟数组
void test02(){//在堆区创建10个整形数据的数组int *arr = new int[10];//10代表数组由10个元素for (int i = 0;i < 10;i++) {arr[i] = i + 100;//给10个元素赋值为100~109}for (int i = 0;i < 10;i++) {cout << arr[i] << endl;}//释放堆区数组delete[] arr;
}
int main() {test01();system("pause");return 0;
}13.引用
引用-》给变量起别名
 //13.1语法:数据类型  &别名 = 原名
 int a = 10;
 int &b = a;//引用必须初始化
 int c = 20;
 b = c;//赋值操作,而不是更改引用,引用初始化后不可以改变
 cout<< a <<endl;//20 
 cout<< b <<endl;//20
 cout << c <<endl;//20
//13.2引用传递
 //引用传递,形参会修饰实参(别名可以跟实名相同)
 void Swap(int &a,int &b){
        int temp = a;
        a = b;
        b = temp;
 }
 //不能返回局部变量的引用(vs2022可以)
 int&  test01() {
      int a = 10;//局部变量
      return a;
 }
 //如果函数的返回值是引用,函数的调用可以作为左值
 int&  test02() {
     static int a = 20;//返回静态变量引用
     return a;
 }
int main(){
       int ref = test01();
       cout<<"ref"<<endl;//10
       cout<<"ref"<<endl;//乱码
  
       int &ref2 = test02();
       cout<<ref2<<endl;//20
       test02() = 1000;
       cout<<ref2<<endl;//1000
 }
//13.3引用本质:引用在c++内部实现是一个指针常量,但是所有的指针操作编译器都帮我们做了
 #include<iostream>
 using namespace std;
void func(int& ref) {
     ref = 100;
 }
int main() {
     
     int a = 10;
     //自动转换为int* const ref = &a;指针常量是指针指向不可改,也说明为什么引用不可更改
     int& ref = a;
     ref = 20;//内部发现是引用,自动帮我们转换为:*ref = 20;
     cout << a << endl;//20
     cout << ref << endl;//20
    func(a);
     system("pause");
     return 0;
 }
//13.4常量引用
 #include<iostream>
 using namespace std;
 //引用使用的场景,通常用来修饰形参
 void showValue(const int &val){
     //val = 1000;
     cout << "val=" << val << endl;//100
 }
    int main() {
         //int& ref = 10;//引用必须引进一块合法的内存空间,报错
     //加上const后,编译器将代码修改为int temp = 10;const int &ref = temp;
     //const int& ref = 10;
     //ref = 20;//报错,加上const后不可以修改变量
         int a = 100;
         showValue(a); //函数中利用常量引用防止操作修改实参
         cout << a << endl;//100
     system("pause");
     return 0;
 }
14.函数
 //14.1函数的默认参数:
 //语法:返回值类型 函数名 (参数 = 默认值){}
 #include<iostream>
 using namespace std;
 //1.如果某个位置参数有默认值,那么从这个位置往后,从左到右,必须都要有默认值
 int func(int a,int b,int c = 10) {
     return a + b + c;
 }
 //2.如果函数声明有默认值,函数实现的时候就不能有默认函数
 int func2(int a = 10, int b = 10);
 int func2(int a,int b) {
     return a + b;
 }
 int main() {
    cout << func(20, 20) << endl;//50
     cout << func2(20, 20) << endl;//40
     system("pause");
     return 0;
 }
//14.2函数占位参数
 //c++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置
 //语法:返回值类型 函数名 (数据类型){}
 //函数占位参数,占位参数也可以有默认参数
 #include<iostream>
 using namespace std;
void func(int a, int) {
     cout << "this is func" << endl;
 }
 int main() {
func(10, 10);//占位参数必须填补
    system("pause");
     return 0;
 }
//14.3函数重载
 //14.3.1
 //作用:函数名可以相同,提高复用性
 //条件:1.作用域相同,2.函数名相同,3.函参类型不同或者个数不同或者顺序不同
 //函数的返回值不可以作为函数重载的条件
#include<iostream>
 using namespace std;
 //同作用域
 void func() {
     cout << "func的调用" << endl;
 }
 void func(int a) {
     cout << "func(int a)的调用" << endl;
 }
 void func(double a) {
     cout << "func(double a)的调用" << endl;
 }
 void func(int a, double b) {
     cout << "func(int a, double b)的调用" << endl;
 }
 void func(double a, int b) {
     cout << "func(double a,int b)的调用" << endl;
 }
 //函数的返回值不可以作为函数重载的条件
 //int func(double a, int b) {
 //    cout << "func(double a, int b)的调用" << endl;
 //}
int main() {
    func();
     func(10);
     func(3.14);
     func(10,3.14);
     func(3.14,10);
    system("pause");
     return 0;
 }
//14.3.2函数重载注义事项
 #include<iostream>
 using namespace std;
 //1.引用作为重载条件
 void func(int& a) {//可读写
     cout << "func(int &a)调用" << endl;
 }
 void func(const int& a) {//只可读
     cout << "func(const int &a)调用" << endl;
 }
 //2.函数重载碰到函数默认参数
 void func2(int a, int b = 10) {
     cout << "func2(int a,int b = 10)调用" << endl;
 }
 void func2(int a) {
     cout << "func2(int a)调用" << endl;
 }
 int main() {
    int a = 10;
     func(a);//调用无const
     func(10);//调用有const
    //func2(10);//碰到默认参数产生歧义,需避免
     system("pause");
     return 0;
 }
15.类与对象
 //面向对象三大特性:封装,继承,多态
 //万事万物皆为对象,对象上有其属性和行为
 //类中的属性和行为统一称为成员
 //属性:成员属性成员变量
 //行为:成员函数成员方法
 //15.1封装
 //意义:在设计类的时候,属性和行为写在一起,表现事务
 //语法:class 类名{  访问权限:属性/行为  };
 //封装一个学生类
 #include<iostream>
 using namespace std;
 class Student {
 public://公共访问的权限
         //属性:姓名,学号
     string m_Name;
     int m_Id;
     void showStudent() {//行为:展示学生姓名,学号
         cout << m_Name << m_Id << endl;
     }
     void setName(string name) {
         m_Name = name;
     }
     void setId(int id) {
         m_Id = id;
     }
 };
 int main() {
         
     Student s1;//实例化(创建学生对象)
     s1.setName("张三");//行为给属性赋值
     s1.setId(1);
     s1.showStudent();
       Student s2;
        s2.m_Name = "李四";//直接赋值
        s2.m_Id = 2;
    system("pause");
     return 0;
 }
//15.2权限
 //三种权限:
 //公共权限      public          类内可以访问      类外可以访问
 //保护权限      protected    类内可以访问      类外不可以访问
 //私有权限      private         类内可以访问      类外不可以访问
 #include<iostream>
 using namespace std;
 class Person {
 public:
     string m_name;//姓名 公共权限
 protected:
     string m_car;//汽车 保护权限
 private:
     int m_password;//银行卡密码 私有权限
 public:
     void func() {
         m_name = "张三";
         m_car = "奔驰";
         m_password = 2501314;
     }
 };
int main() {
    Person p;
     p.m_name = "李四";
         p.func();
     //p.m_car = "奥迪";//保护权限内容,类外访问不到
     //p.m_password = 123456;//私有权限内容,类外访问不到
    system("pause");
     return 0;
 }
15.3struct与class的区别:
 //struct默认权限为公共
 //class默认权限为私有
 #include<iostream>
 using namespace std;
class C1 {
     int m_A;//默认私有权限
 };
 struct C2 {
     int m_A;//默认公共权限
 };
int main() {
    C1 c1;
     //c1.m_A = 10;//错误,访问权限私有
     C2 c2;
     c2.m_A = 10;//正确,访问权限公共
    system("pause");
     return 0;
 }
15.4成员属性设为私有
 //1.可以自己控制读写权限
 //2.对于写可以检测数据有效性
 #include<iostream>
 using namespace std;
 #include<string>
class Person {
 public:
     //设置姓名
     void setName(string name) {
         m_Name = name;
     }
     //获取姓名
     string getName() {
         return m_Name;
     }
     //获取年龄
     int getAge() {
         return m_Age;
     }
     //设置偶像
     string setIdol(string idol) {
         m_Idol = idol;
     }
 private:
     string m_Name;//姓名可读可写
     int m_Age;    //年龄只读
     string m_Idol;//偶像只写
 };
int main() {
    Person p;
     //p.m_Name = "张三";//私有不可访问
     //cout << "姓名:" << p.m_Name << endl;
     //姓名设置
     p.setName("张三");
     cout << "姓名:" << p.getName() << endl;;
     //年龄设置
     //p.setAge(20);
     //p.m_Age() = 20;
     cout << "年龄:" << p.getAge() << endl;
     p.setIdol("胡歌");
     //p.m_Idol = "周杰伦";//只写,外界无法访问
    system("pause");
     return 0;
 }
//15.5全局函数与成员函数:
 #include<iostream>
 using namespace std;
class Cube {
 public:
     //成员函数:
     bool isSameByClass(Cube &c) {
         //这里当我们在外面调用成员变量时,一定是通过一个实例化对象a和实例化对象b进行比较,
         //通过对象a调用方法传入对象b的参数,所以参数只需要一个就行了。
         //...
     }
};
//全局函数
 bool isSame(Cube& c1, Cube& c2) {
     //这里使用引用就可以直接把这个全局函数的c1,c2直接指向主函数里的c1,c2储存的值,也就是指针常量,
     //当数据量大时引用就比值传递更加的节省内存了
     //...
 }
 int main() {
    Cube c1;
     Cube c2;
     //...
     //全局函数调用
     bool ret = isSame(c1, c2);
     //...
     //成员函数调用
     ret = c1.isSameByClass(c2);
     //...
     system("pause");
     return 0;
 }
//15.6点圆关系案例
 //point.h
 #pragma once//防止头文件重复包含
 #include<iostream>
 using namespace std;
//点类
 class Point {
 public:
    void setX(int x);
     int getX();
     void setY(int y);
     int getY();
private:
     int m_X;//横坐标
     int m_Y;//纵坐标
 };
//point.cpp
 #include "point.h"
    void Point::setX(int x) {//point::告知成员函数
         m_X = x;
     }
     int Point::getX() {
         return m_X;
     }
     void Point::setY(int y) {
         m_Y = y;
     }
     int Point::getY() {
         return m_Y;
     }
 //circle.h
 #pragma once//防止头文件重复包含
 #include<iostream>
 using namespace std;
 #include"point.h"
class Circle {
 public:
     void setR(int r);
     int getR();
     void setCenter(Point center);
     Point getCenter();
         
 private:
     int m_R;//半径
     Point m_Center;//圆心  //在类中可以让另一个类作为本类中的成员
 };
//circle.cpp
 #include "circle.h"
 //圆类:
     void Circle::setR(int r) {
         m_R = r;
     }
     int Circle::getR() {
         return m_R;
     }
     void Circle::setCenter(Point center) {
         m_Center = center;
     }
     Point Circle::getCenter() {
         return m_Center;
     }
//点圆关系.cpp
 #include<iostream>
 using namespace std;
 #include "point.h"
 #include "circle.h"
//判断点和圆类关系(全局函数)
 void isInCircle(Circle& c, Point& p) {
     //计算两点之间距离  平方
     int distance = pow(c.getCenter().getX() - p.getX(), 2) + pow(c.getCenter().getY() - p.getY(), 2);
     //计算半径平方
     int rDistance = pow(c.getR(), 2);
     //判断圆外
     if (distance == rDistance) {
         cout << "圆上" << endl;
     }
     else if (distance > rDistance) {
         cout << "圆外" << endl;
     }
     else {
         cout << "圆内" << endl;
     }
}
int main() {
    //创建圆
     Circle c;
     c.setR(10);
     Point center;
     center.setX(10);
     center.setY(0);
     c.setCenter(center);
    //创建点
     Point p;
     p.setX(10);
     p.setY(10);
    //判断关系
     isInCircle(c, p);
    system("pause");
     return 0;
 }
16.构造函数和析构函数
 //构造函数:主要作用在于创建对象时为对象的成员赋值,构造函数由编译器自动调用,无需手动调用
 //析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。
 //构造函数语法:类名(){}
 //1.构造函数,没有返回值,不写void
 //2.函数名与类名相同
 //3.构造函数可以有参数,因此可以发生重载
 //4.程序在调用对象时,会自动调用构造,无需手动调用,而且只会调用一次
//析构函数语法:~类名(){}
 //1.析构函数:没有返回值也不写void
 //2.函数名与类名相同,在名称前加符号~
 //3.析构函数不可以有参数,因此不可以发生重载
 //4.程序在对象销毁前会自动调用析构,无需手动调用,而且只会调用一次
 #include<iostream>
 using namespace std;
 //对象的初始化和清理
 //构造函数进行初始化操作
 class Person {
 public://不写作用域的话,默认在private域内,无法访问
     Person() {
         cout << "Person的构造函数调用" << endl;
     }
     //析构函数,进行清理操作
     ~Person() {
         cout << "Person的析构函数调用" << endl;
     }
 };
 //构造和析构都是必须有的实现,如果我们自己不提供,编译器会提供一个空实现的构造和析构
 void test01() {
     Person p;//在栈区的数据,test01执行完毕后,释放这个对象,而释放对象会自动调用析构函数
 }
 int main() {
    test01();
     //Person p;//只会调用析构函数,对象还没销毁,系统就已经结束运行
     system("pause");
     return 0;
 }
//16.1函数分类以及调用
 #include<iostream>
 using namespace std;
//构造函数的分类即调用
 //按参数分类:       无参构造(默认构造)和有参构造
 //按类型分类:       普通构造           ,拷贝构造
 class Person {
 public:
     //构造函数
     Person() {
         cout << "Person的无参构造函数调用" << endl;
     }
     Person(int a) {
         age = a;
         cout << "Person的有参构造函数调用" << endl;
     }
     //拷贝函数
     Person(const Person &p) {//const避免原函数被改
         age = p.age;//将传入的人身上的所有属性,拷贝到我身上
         cout << "Person的拷贝构造函数调用" << endl;
     }
     ~Person() {
         cout << "Person析构函数调用" << endl;
     }
     int age;
 };
 //调用
 void test01() {
     //括号法:
     //Person p1;//默认构造函数调用
     //Person p2(10);//有参构造函数
     //Person p3(p2);//拷贝构造函数
    //注意事项1:调用默认构造函数时候,不要加()
     //因为下面这行代码,编译器会认为时是一个函数的声明,不会认为在创建对象
     //Person p1();
    //2.显示法:
     Person p1;
     Person p2 = Person(10);//有参构造
     Person p3 = Person(p2);//拷贝构造
     //Person(10);//匿名对象  特点:当前执行完后,系统会立即回收掉匿名对象
     
     //注意事项2:不要利用拷贝构造函数,初始化匿名对象,编译器会认为Person(p3) == Person p3;
     //Person(p3);//"Person p3"重定义.
    //3.隐式转换法
     Person p4 = 10;//相当于写了Person p4 = Person(10);有参构造
     Person p5 = p4;//拷贝构造
 }
 int main() {
    test01();
     system("pause");
     return 0;
 }
//16.2拷贝构造函数调用时机
 //1.使用一个已经创建完毕的对象来初始化一个新对象
 //2.值传递的方式给函数参数传值
 //3.值方式返回局部对象
 #include<iostream>
 using namespace std;
class Person {
 public:
     Person() {
         cout << "Person默认构造函数调用" << endl;
     }
     Person(int age) {
         cout << "Person有参构造函数调用" << endl;
         m_Age = age;
     }
     Person(const Person& p) {
         cout << "Person拷贝构造函数调用" << endl;
         m_Age = p.m_Age;
     }
     ~Person() {
         cout << "Person析构函数调用" << endl;
     }
    int m_Age;
 };
 //1.使用一个已经创建完毕的对象来初始化一个新对象
 void test01(){
     Person p1(20);
     Person p2(p1);
 }
 //2.值传递的方式给函数参数传值
 void doWork(Person p){}
void test02() {
     Person p;
     doWork(p);
 }
 //3.值方式返回局部对象
 Person doWork2() {
     Person p1;
     cout << (int*)&p1 << endl;
     return p1;
 }
void test03() {
     Person p = doWork2();
     cout << (int*)&p << endl;
 }
int main() {
    //test01();
     //test02();
     test03();
     system("pause");
     return 0;
 }
//16.3构造函数调用规则
 //16.3.1.创建一个类,c++编译器会给每个类都添加至少3个函数:
 //默认构造    (空实现)
 //析构函数    (空实现)
 //拷贝构造    (值拷贝)
//16.3.2. 如果我们写了有参构造函数,编译器就不再提供默认构造,依然提供拷贝构造
 //16.3.3.如果我们写了拷贝构造函数,编译器就不再提供其他普通构造函数
//16.4浅拷贝与深拷贝
 //浅拷贝:简单的赋值操作
 //深拷贝:在对去重新申请空间,进行拷贝操作。
 //如果利用编译器提供的拷贝构造函数,会做浅拷贝操作,浅拷贝带来的问题就是堆区的内存重复释放
 //浅拷贝的问题,要用深拷贝来解决问题,自己实现拷贝构造函数。
 #include<iostream>
 using namespace std;
class Person {
 public:
     Person() {
         cout << "Person默认构造函数调用" << endl;
     }
     Person(int age,int height) {
         m_Height = new int(height);
         cout << "Person有参构造函数调用" << endl;
         m_Age = age;
     }
     //拷贝构造函数
     Person(const Person& p) {
         cout << "拷贝构造函数调用" << 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;
     }
    int m_Age;
     int* m_Height;
 };
void test01() {
     Person p1(18,160);
     cout << "p1的年龄为:" << p1.m_Age << "身高为:" << *p1.m_Height << endl;
     Person p2(p1);
     cout << "p2的年龄为:" << p2.m_Age << "身高为:" << *p2.m_Height << endl;
 }
 int main() {
    test01();
     system("pause");
     return 0;
 }
//16.5初始化列表
 //语法:构造函数():属性1(值1),属性2(值2) ... {}
 #include<iostream>
 using namespace std;
 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 test01() {
     Person p(10,20,30);
     cout << "m_A = " << p.m_A << endl;
     cout << "m_B = " << p.m_B << endl;
     cout << "m_C = " << p.m_C << endl;
 }
 int main() {
    test01();
     system("pause");
     return 0;
 }
17.类对象作为类成员
 //c++类中的成员可以是另一个类中的对象,我们称之该成员为对象成员
 #include<iostream>
 using namespace std;
 #include<string>
 class Phone {
 public:
     Phone(string pName) {
         cout << "phone的构造函数调用" << endl;
         m_PName = pName;
     }
     ~Phone() {
         cout << "Phone的析构函数调用" << endl;
     }
     //手机品牌
     string m_PName;
 };
//人类
 class Person
 {
 public:
     //默认执行Phone m_Phone = pName;  隐式转换法
     Person(string name, string pName) :m_Name(name), m_Phone(pName) 
     {
         cout << "Person的构造函数调用" << endl;
     }
     ~Person() {
         cout << "Person的析构函数调用" << endl;
     }
     string m_Name;//姓名
     Phone m_Phone;//手机
 };
//当其他类对象作为本类成员,构造时候先构造对象,在构造自身,析构顺序与之相反
 void test01() {
     Person p("张三", "苹果");
     cout << p.m_Name << "拿着:" << p.m_Phone.m_PName << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
18.静态成员(static+成员)
 //18.1静态成员变量:
 //1.所有对象共享同份数据
 //2.在编译阶段分配内存
 //3.类内声明,类外初始化
 #include<iostream>
 using namespace std;
 #include<string>
 class Person {
 public:
     static int m_A;
     //静态成员变量也是有访问权限的
 private:
     static int m_B;
 };
 int Person::m_A = 100;
 int Person::m_B = 200;
void test01() {
     Person p;
     cout << p.m_A << endl;//100
     Person p2;
     p2.m_A = 200;
     cout << p.m_A << endl;//200
 }
void test02() {
     //静态成员变量,不属于某个对象上,所有对象都共享同一份数据
     //因此静态成员白能量有两种方式
     //1.通过对象进行访问
     /*Person p;
     cout << p.m_A << endl;*/
     //2.通过类名进行访问
     cout << Person::m_A << endl;
     //cout << Person::m_B << endl;//类外访问不到私有静态成员变量
 }
 int main() {
    test01();
     test02();
     system("pause");
     return 0;
 }
//18.2静态成员函数:
 //1.所有对象共享同一个函数:
 //2.静态成员函数只能访问静态成员变量
 #include<iostream>
 using namespace std;
class Person
 {
 public:
     //静态成员函数
     static void func() {
         m_A = 100;//静态成员函数可以访问静态成员变量
         //m_B = 200;//静态成员函数不可以访问非静态成员变量
         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 = 0;
void test01() {
     //静态成员变量两种访问方式:
     //1.通过对象进行访问
     Person p;
     p.func();
     //2.通过类名进行访问
     Person::func();
     //Person::func2();//类外访问不到私有静态成员函数
 }
int main() {
    system("pause");
     return 0;
 }
//18.3成员变量与成员函数是分开存储的
 //每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类的对象会共用一块代码
//this指针是隐含每一个非静态成员函数内的一种指针
 //this指针不需要定义,直接使用即可
 //用途:1.当形参和成员变量同名时,可用this指针类区分
 //           2.在类的非静态成员函数中返回对象本身,可用return *this;
 //引用返回,返回的是原始对象的直接引用
 //值返回一个对象时,会触发对象的复制构造函数或移动构造函数,会创建一个新的对象,但无法修改原始对象的状态
 #include<iostream>
 using namespace std;
class Person {
 public:
     Person(int age) {
         //age = age;//-858993460
         //this指针指向被调用的成员函数所属的对象
         this->age = age;//18
     }
    Person& PersonAddAge(Person &p){//返回本体需要以引用的方式返回
         this->age += p.age;
         //this指向p2的指针,而*this指向的就是p2这个对象本体
         return *this;
     }
    int age;
 };
//1.解决名称冲突
 void test01() {
     Person p1(18);
     cout << "p1的年龄为:" << p1.age << endl;
 }
void test02() {
     Person p1(10);
     Person p2(10);
     //链式编程思想:无限追加
     p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
     cout << "p2的年龄为:" << p2.age << endl;
 }
int main() {
    //test01();
     test02();
     system("pause");
     return 0;
 }
//18.4空指针访问成员函数
 #include<iostream>
 using namespace std;
class Person {
 public:
     void showClassName() {
         cout << "this is Person class" << endl;
     }
     void showPersonAge() {
         //报错原因,传入指针为空
         if (this == NULL) {//针对空指针做对应,就不会把报错了
             return;
         }
         cout << "age = " << m_Age << endl;
     }
    int m_Age;
 };
void test01() {
     Person* p = NULL;
     p->showClassName();
     p->showPersonAge();
 }
 int main() {
    test01();
     system("pause");
     return 0;
 }
//18.5const修饰成员函数
 //1.常函数:
 //常函数内不可以修改成员属性
 //成员属性声明时加关键字mutable后,在常函数中依然可以修改
 //2.常对象:
 //常对象只能调用常函数
 #include<iostream>
 using namespace std;
class Person {
 public:
     //this指针本质:指针常量,指针指向不可改
     //const Person * const this
     //在成员函数后面加上const,修饰的时this指向,让指针指向的值不可以修改
     void showPerson() const {//在成员函数后加const,变为常函数
         //this->m_A = 100;
         //this = NULL;//this指针不可以修改指针指向
         this->m_B = 100;
         cout <<"m_B为:" << m_B << endl;
     }
    void func() {
         m_A = 100;
     }
    int m_A;
     mutable int m_B;//特殊变量,即使在常函数中,也可以修改这个值,只需加上关键字mutable
 };
void test02() {
     const Person p;//在对象前加const,变为常对象
     //p.m_A = 100;
     p.m_B = 100;//m_B是特殊值,在常对象下也可以修改
     //常对象只能调用常函数
     p.showPerson();
     //p.func();//常对象不可以修改普通成员函数,因为普通成员函数可以修改属性
 }
int main() {
     
     //test01();
     test02();
     system("pause");
     return 0;
 }
//18.6友元
 //实现:全局函数做友元,类做友元,成员函数做友元。
//18.6.1全局函数做友元:
 #include<iostream>
 using namespace std;
 #include<string>
//建筑物类
 class Building {
     //goodGay全局函数是Building好朋友,可以访问Building中私有成员
     friend void goodGay(Building* building);
 public:
     Building() {
         m_Sitting = "客厅";
         m_BedRoom = "卧室";
     }
 public:
     string m_Sitting;//客厅
 private:
     string m_BedRoom;//卧室
 };
//全局函数
 void goodGay(Building *building) {
     cout << "好基友全局函数正在访问:" << building->m_Sitting << endl;
     cout << "好基友全局函数正在访问:" << building->m_BedRoom << endl;
 }
void test01() {
     Building building;
     goodGay(&building);
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//18.6.2类做友元:
 #include<iostream>
 using namespace std;
 #include<string>
class Building;
class GoodGay {
 public:
     GoodGay();//好基友
     void visit();//访问Building中的属性
     Building * building;
 };
//建筑物类
 class Building {
     //GoogGay类是本类的好朋友,可以访问本类中私有成员
     friend class GoodGay;
 public:
     Building();
 public:
     string m_SittingRoom;//客厅
 private:
     string m_BedRoom;//卧室
 };
//类外写成员函数
 Building::Building() {
     m_SittingRoom = "客厅";
     m_BedRoom = "卧室";
 }
GoodGay::GoodGay() {
     //创建一个建筑物对象
     building = new Building;//building指向这个对象
 }
void GoodGay::visit() {
     cout << "好基友正在访问你的:" << building->m_SittingRoom << endl;
     cout << "好基友正在访问你的:" << building->m_BedRoom << endl;
 }
void test01() {
     GoodGay gg;
     gg.visit();
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//18.6.3成员函数做友元
 #include<iostream>
 using namespace std;
 #include<string>
class Building;
class GoodGay {
 public:
     GoodGay();
    void visit();//让visit函数可以访问Building中的私有成员
     void visit2();//让visit2函数不可以访问Building中私有成员
     Building* building;
 };
class Building {
 //告诉编译器,GoodGay类下的visit成员函数作为本类的好朋友,可以访问私有成员
     friend void GoodGay::visit();
 public:
     Building();
 public:
     string m_SittingRoom;//客厅
 private:
     string m_BedRoom;//卧室
 };
//类外实现成员函数:
 Building::Building() {
     m_SittingRoom = "客厅";
     m_BedRoom = "卧室";
 }
GoodGay::GoodGay() {
     building = new Building;
 }
void GoodGay::visit(){
     cout << "visit函数正在访问:" << building->m_SittingRoom << endl;
     cout << "visit函数正在访问:" << building->m_BedRoom << endl;
 }
 void GoodGay::visit2(){
     cout << "visit函数正在访问:" << building->m_SittingRoom << endl;
     //cout << "visit函数正在访问:" << building->m_BedRoom << endl;
 }
void test01() {
     GoodGay gg;
     gg.visit();
     gg.visit2();
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
19.运算符重载
 //对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
 //调用的重载函数时候不用写operator,这是因为C++语法规定,当你使用重载的运算符时,你只需像使用内置类型的运算符一样使用它,提高了代码的可读性和易用性
 //19.1加号运算符重载
 //对于内置的数据类型的表达式的运算符是不可能改变的
 //不要滥用运算符重载
 #include<iostream>
 using namespace std;
 #include<string>
class Person {
 public:
     //1.成员函数重载+号
     /*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;
     }*/
     int m_A;
     int m_B;
 };
//2.全局函数重载+号
 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 operator+(Person& p1, int num) {
     Person temp;
     temp.m_A = p1.m_A + num;
     temp.m_B = p1.m_B + num;
     return temp;
 }
void test01() {
     Person p1;
     p1.m_A = 10;
     p1.m_B = 10;
     Person p2;
     p2.m_A = 10;
     p2.m_B = 10;
    //成员函数重载本质调用
     //Person p3 = p1.operator+(p2);
     //全局函数重载本质调用
     //Person p3 = operator+ (p1, p2);
     Person p3 = p1 + p2;//简化版本
     
     //运算符重载,也可以发生函数重载
     Person p4 = p1 + 100;//Person + int
    cout << "p3.m_A=" << p3.m_A << endl;
     cout << "p3.m_B=" << p3.m_B << endl;
    cout << "p4.m_A=" << p4.m_A << endl;
     cout << "p4.m_B=" << p4.m_B << endl;
 }
int main() {
     test01();
     system("pause");
     return 0;
 }
//19.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:
     //利用成员函数重载左移运算符    p.operator << (cout)   简化版本: p << cout
     //不会利用成员函数重载<<运算符,只能利用全局函数重载左移运算符
     int m_A;
     int m_B;
 };
ostream &operator<<(ostream &cout,Person &p) {  //本质:operator << (cout,p) 简化: cout << p
     cout << "m_A = " << p.m_A << "  m_B = " << p.m_B;
     return cout;
 }
void test01(){
     Person p(10,10);
     //p.m_A = 10;
     //p.m_B = 10;
     cout << p << "  Hello World" << endl;
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//19.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;
         }
     //重载后置++运算符
     MyInteger operator++(int) {  //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 test01() {
     MyInteger myint;
     cout << ++(++myint) << endl;
 }
void test02() {
     MyInteger myint;
     cout << myint++ << endl;
     cout << myint << endl;
 }
 int main() {
    //test01();
     test02();
     system("pause");
     return 0;
 }
//19.4赋值运算符重载
 #include <iostream>  
 using namespace std;
class Person {
 public:
     Person(int age) {
         m_Age = new int(age);
     }
    ~Person() {//浅拷贝时,堆区内会存重复释放导致程序崩溃
         if (m_Age != NULL) {
             delete m_Age;
             m_Age = NULL;
         }
     }
    //重载赋值运算符
     Person& operator=(Person &p) {
        //编译器的重载赋值运算符是提供浅拷贝
         //m_Age = p.m_Age;
         
         //应先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
         if (m_Age != NULL) {
             delete m_Age;
             m_Age = NULL;
             //深拷贝
             m_Age = new int(*p.m_Age);
         }
         return *this;//返回对象自身
     }
     int *m_Age;
 };
void test01() {
    Person p1(18);
     Person p2(20);
     Person p3(30);
     p3 = p2 = p1;//赋值操作
     cout << "p1的年龄为:" << *p1.m_Age << endl;
     cout << "p3的年龄为:" << *p3.m_Age << endl;
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//19.5关系运算符重载
 #include<iostream>
 using namespace std;
class Person {
 public:
     Person(string name,int age) {
         m_Name = name;
         m_Age = age;
     }
    bool operator==(Person& p) {
         if (this->m_Age == p.m_Age && this->m_Name == p.m_Name) {
             return true;
         }
         return false;
     }
     string m_Name;
     int m_Age;
 };
void test01() {
     Person p1("张三", 18);
     Person p2("李四", 19);
     if (p1 == p2) {
         cout << "p1和p2相等" << endl;
     }
     else {
         cout << "p1和p2不相等" << endl;
     }
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//19.6函数调用运算符重载
 #include<iostream>
 using namespace std;
//打印输出类
 class MyPrint {
 public:
     //重载函数调用运算符
     void operator()(string test) {
         cout << test << endl;
     }
 };
void test01() {
     MyPrint myprint;
     myprint("helloworld");//由于使用起来非常类似于函数调用,因此称为仿函数
 }
//仿函数非常灵活,没有固定写法
 //加法类
 class MyAdd {
 public:
     int operator()(int num1, int num2) {
         return num1 + num2;
     }
 };
void test02() {
     MyAdd myadd;
     int ret = myadd(10, 20);
     cout << "ret =" << ret << endl;//30
     //匿名函数对象
     cout << MyAdd()(10, 20) << endl;//30
 }
int main() {
    test01();
     test02();
     system("pause");
     return 0;
 }
20.继承
 #include <iostream>  
 using namespace std;
//普通实现页面
 class BasePage {
 public:
     void header() {
         cout << "首页,公开课,登录,注册" << endl;
     }
     void footer() {
         cout << "帮助中心,交流合作,站内地图...(公共底部)" << endl;
     }
 };
//继承的好处:减少重复的代码
 //语法:class 子类:继承方式 父类
 //子类也成为派生类
 //父类也成为基类
 //Java页面
 class Java :public BasePage {
 public:
     void content() {
         cout << "java学科视频" << endl;
     }
 };
//Python页面
 class Python :public BasePage {
 public:
     void content() {
         cout << "Python学科视频" << endl;
     }
 };
//C++页面
 class Cpp :public BasePage {
 public:
     void content() {
         cout << "Cpp学科视频" << endl;
     }
 };
void test01() {
     cout << "-----------------------------" << endl;
     cout << "Java下载视频页面如下:" << endl;
     Java ja;
     ja.header();
     ja.footer();
    cout << "-----------------------------" << endl;
     cout << "Python下载视频页面如下:" << endl;
     Python py;
     py.header();
     py.footer();
    cout << "-----------------------------" << endl;
     cout << "Cpp下载视频页面如下:" << endl;
     Cpp c;
     c.header();
     c.footer();
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//20.2继承方式
 //1.公共继承,2.保护继承,3.私有继承
 #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 = 10;//父类中的保护权限成员到子类中依然是保护权限
         //m_C = 10;//父类中的私有权限成员子类访问不到
     }
 };
void test01() {
     Son1 s1;
     s1.m_A = 100;
     //s1.m_B = 100;//到Son1中m_B是保护权限,类外访问不到
 }
class Base2 {
 public:
     int m_A;
 protected:
     int m_B;
 private:
     int m_C;
 };
class Son2 :protected Base2 {
 public:
     void func() {
         m_A = 100;//父类中公共成员  到子类变为保护权限
         m_B = 100;//父类中保护成员  到子类变为保护权限
         //m_C = 100;//父类中私有成员 子类访问不到
     }
 };
void test02() {
     Son2 s2;
     //s2.m_A = 100;//在Son2中 m_A变为保护权限,因此类外访问不到
     //s2.m_B = 100;//在Son2中 m_B变为保护权限,因此类外访问不到
 }
//私有继承
 class Base3 {
 public:
     int m_A;
 protected:
     int m_B;
 private:
     int m_C;
 };
class Son3 :private Base3 {
 public:
     void func() {
         m_A = 100;//父类中公共成员到了子类中变为私有成员
         m_B = 100;//父类中保护成员到了子类中变为私有成员
         //m_C = 100;//父类中私有成员,子类访问不到
     }
 };
void test03() {
     Son3 s1;
     //s1.m_A = 1000;//到Son3中变为私有成员 类外访问不到
     //s1.m_B = 1000;//到Son3中变为私有成员 类外访问不到
 }
class GrandSon3 :public Son3 {
 public:
     void func() {
         //m_A = 100;//到了Son3中,m_A变为私有,即使是儿子,也是访问不到
         //m_B = 100;//到了Son3中,m_A变为私有,即使是儿子,也是访问不到
     }
 };
int main() {
    system("pause");
     return 0;
 }
//20.3继承中对象模型
 #include<iostream>
 using namespace std;
class Base {
 public:
     int m_A;
 protected:
     int m_B;
 private:
     int m_C;
 };
class Son :public Base {
 public:
     int m_D;
 };
void test01() {
     //父类中所有非静态成员属性都会被子类继承下去
     //父类中私有成员属性是被编译器给隐藏了,因此是访问不到,但是确实被继承下去了
     cout << "sizeof of Son = " << sizeof(Son) << endl;//16
 }
 int main() {
    test01();
     system("pause");
     return 0;
 }
//20.4继承中构造和析构顺序
 //子类继承父类后,当继承子类对象,也会调用父类的构造函数
 //继承中的构造和析构顺序如下:
 //先构造父类,再构造子类,析构的顺序与构造的顺序相反。
//20.5继承同名成员处理方式
 //访问子类同名成员,直接访问即可
 //访问父类同名成员,需要加作用域
 #include<iostream>
 using namespace std;
 class Base {
 public:
     Base() {
         m_A = 100;
     }
    void func() {
         cout << "Base-func()调用" << endl;
     }
    void func(int a) {
         cout << "Base-func(int a)调用" << endl;
     }
    int m_A;
 };
class Son:public Base {
 public:
     Son() {
         m_A = 200;
     }
    void func() {
         cout << "Son-func()调用" << endl;
     }
    int m_A;
 };
void test01() {
     Base b;
     cout << "m_A = " << b.m_A << endl;//100
     Son s;
     cout << "m_A = " << s.m_A << endl;//200
     //如果通过子类对象访问父类中同名成员,需要加作用域
     cout << "m_A = " << s.Base::m_A << endl;//100
 }
void test02() {
     Son s;
     s.func();//直接调用子类中的同名成员
     s.Base::func();//调用父类中同名成员函数
     //如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏父类中所有同名成员函数
     //s.func(100);
     s.Base::func(100);
 }
int main() {
    //test01();
     test02();
     system("pause");
     return 0;
 }
//20.6继承中同名静态成员处理方式
 #include<iostream>
 using namespace std;
 class Base {
 public:
    static int m_A;
     static void func() {
         cout << "Base-static void func()" << endl;
     }
    static void func(int a) {
         cout << "Base-static void func(int a)" << endl;
     }
 };
 int Base::m_A = 100;
class Son:public Base {
 public:
    static void func() {
         cout << "Son-static void func()" << endl;
     }
    static int m_A;
 };
 int Son::m_A = 200;
//同名静态成员变量
 void test01() {
     //通过对象访问
     cout << "通过对象访问" << endl;
     Son s;
     cout << "Son下m_A = " << s.m_A << endl;
     cout << "Base下m_A = " << s.Base::m_A << endl;
     //通过类名访问
     cout << "通过类名访问" << endl;
     cout << "Son下m_A = " << Son::m_A << endl;
     cout << "Base下m_A = " << Base::m_A << endl;
     //1::代表通过类名方式访问,2::代表访问父类作用域下
     cout << "Base下m_A = " << Son::Base::m_A << endl;
 }
//同名静态成员函数
 void test02() {
     //通过对象访问
     cout << "通过对象访问" << endl;
     Son s;
     s.func();
     s.Base::func();
     //通过类名进行访问
     cout << "通过类名访问" << endl;
     Son::func();
     Son::Base::func();
     //子类出现和父类同名静态成员函数,也会隐藏父类中所有同名成员函数
     //如果像访问父类中被隐藏同名成员,需要加作用域
     Son::Base::func(100);
 }
int main() {
//test01();
    system("pause");
     return 0;
 }
//20.7多继承语法
 //c++实际开发中不建议用多继承
 #include<iostream>
 using namespace std;
class Base1 {
 public:
     Base1() {
         m_A = 100;
     }
    int m_A;
 };
class Base2 {
 public:
     Base2() {
         m_A = 200;
         m_B = 200;
     }
     int m_A;
     int m_B;
 };
//子类需要继承Base1和Base2
 //语法:class 子类 :继承方式 父类1,继承方式 父类2...
 class Son :public Base1, public Base2 {
 public:
     Son() {
         m_C = 300;
         m_D = 400;
     }
     int m_C;
     int m_D;
 };
void test01() {
     Son s;
     cout << "sizeof Son = " << sizeof(s) << endl;
     cout << "Base1::m_A = " << s.Base1::m_A << endl;
     //当父类中出现同名成员,需要加作用域区分
     cout << "Base2::m_A = " << s.Base2::m_A << endl;
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//20.8菱形继承
 //两个派生类继承同一个基类
 //又有某个类同时继承这两个派生类
 //这种继承被称为菱形继承,或者钻石继承
 #include<iostream>
 using namespace std;
//动物类
 class Animal {
 public:
     int m_Age;
};
//利用虚继承解决菱形继承问题
 //继承之前加上关键字virtual变为虚继承
 //Animal类称为虚基类
 //羊类
 class Sheep :virtual public Animal{};
//驼类
 class Tuo :virtual public Animal {};
//羊驼类
 class SheepTuo :public Sheep, public Tuo {
};
void test01() {
     SheepTuo st;
     st.Sheep::m_Age = 18;
     st.Tuo::m_Age = 28;
     //当菱形继承,两个父类拥有相同数据,需要加以作用域区分
     cout << "st.Sheep::m_Age =" << st.Sheep::m_Age << endl;
     cout << "st.Tuo::m_Age =" << st.Tuo::m_Age << endl;
     cout << "st.m_Age = " << st.m_Age << endl;
     //菱形继承导致数据有两份,资源浪费
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
21.多态
 //静态多态:函数重载和运算符重载属于静态多态,复用函数名
 //动态多态:派生类和虚函数实现运行时多态
 //静态多态和动态多态区别:
 //静态多态的函数地址早绑定 - 编译阶段确定函数地址
 //动态多态的函数地址晚绑定 - 运行阶段确定函数地址
 //vfptr    -       虚函数指针:  v -  virtual     f  -  function       ptr  -  pointer
 //vftable   -    虚函数表 :    v -  virtual      f  -  function     table  -  table
 //多态的优点:
 //代码组织结构清晰
 //可读性强
 //利于前期和后期的扩展以及维护
 #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.子类重写父类的虚函数
//动态多态使用
 //父类的指针或者引用 执行子类对象
//执行说话函数
 //地址早绑定 在编译阶段确定函数地址
 //如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定
 void doSpeak(Animal &animal) {//Animal &animal = cat;父类的引用指向子类对象
     animal.speak();
 }
void test01() {
     Cat cat;
     doSpeak(cat);
    Dog dog;
     doSpeak(dog);
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//21.2纯虚函数和抽象类
 //纯虚函数语法:virtual 返回值类型 函数名   (参数列表) =   0;
 //当类中有了纯虚函数,这个类也称为抽象类
 //抽象类特点:
 //1.无法实例化对象
 //2.子类必须重写抽象类中的纯虚函数,否则也属于抽象类
 #include<iostream>
 using namespace std;
class Base {
 public:
     //纯虚函数
     //只要有一个纯虚函数,这个类称为抽象类
     virtual void func() = 0;
 };
class Son :public Base {
 public:
     virtual void func() {
         cout << "func()函数调用" << endl;
     };
 };
void test01() {
     //Base b;//抽象类无法实例化对象
     //new Base;//抽象类无法实例化对象
     //Son s;//子类必须重写父类中的纯虚函数
     Base* base = new Son;
     base->func();
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//21.3虚析构和纯虚析构
 #include<iostream>
 using namespace std;
 #include<string>
class Animal {
 public:
     Animal() {
         cout << "Animal构造函数调用" << endl;
     }
    //利用虚析构可以解决,父类指针释放子类对象时不干净的问题
     /*virtual ~Animal(){
         cout << "Animal析构函数调用" << endl;
     }*/
    virtual ~Animal() = 0;//纯虚析构  需要声明也需要实现
     //有了纯虚析构之后,这个类也属于抽象类,无法实例化对象
     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);
     }
    ~Cat() {
         if (m_Name != NULL) {
             cout << "Cat析构函数调用" << endl;
             delete m_Name;
             m_Name = NULL;
         }
     }
    virtual void speak() {
         cout << *m_Name << "小猫在说话" << endl;
     }
    string *m_Name;
 };
void test01() {
     Animal* animal = new Cat("汤姆");
     animal->speak();
     //父类指针析构函数时候,不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄露
     delete animal;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//21.4案例
 #include<iostream>
 using namespace std;
 #include<string>
//抽象出不同零件类
//CPU类
 class CPU
 {
 public:
     virtual void calculate() = 0;//计算函数
 };
//显卡类
 class VideoCard {
 public:
     virtual void display() = 0;//显示函数
 };
//内存条类
 class Memory {
 public:
     virtual void storage() = 0;//存储函数
 };
//电脑类
 class Computer {
 public:
     Computer(CPU* cpu, VideoCard* vc, Memory* mem) {
         m_cpu = cpu;
         m_vc = vc;
         m_mem = mem;
     }
    //提供工作的函数
     void work() {
         //让零件工作起来,调用接口
         m_cpu->calculate();
         m_vc->display();
         m_mem->storage();
     }
    //提供析构函数,释放3个电脑零件
     ~Computer() {
        //释放cpu零件
         if (m_cpu != NULL) {
             delete m_cpu;
             m_cpu = NULL;
         }
        //释放显卡零件
         if (m_vc != NULL) {
             delete m_vc;
             m_vc = NULL;
         }
        //释放内存条文件
         if (m_mem != NULL) {
             delete m_mem;
             m_mem = NULL;
         }
     }
private:
     CPU* m_cpu;//CPU的零件指针
     VideoCard* m_vc;//显卡的零件指针
     Memory* m_mem;//内存条的零件指针
 };
//具体厂商
 //intel厂商
 class IntelCpu :public CPU {
     void calculate() {
         cout << "Intel的CPU开始计算了" << endl;
     }
 };
class IntelVideoCard :public VideoCard {
     void display() {
         cout << "Intel的显卡开始演示了" << endl;
     }
 };
class IntelMemory :public Memory {
     void storage() {
         cout << "Intel的内存条开始读取数据了" << endl;
     }
 };
//Lenovo厂商
 class LenovoCPU :public CPU {
     void calculate() {
         cout << "Lenovo的CPU开始计算了" << endl;
     }
 };
class LenovoVideoCard :public VideoCard {
     void display() {
         cout << "Lenovo的显卡开始演示了" << endl;
     }
 };
class LenovoMemory :public Memory {
     void storage() {
         cout << "Lenovo的内存条开始读取数据了" << endl;
     }
 };
void test01() {
     //第一台电脑零件
     CPU* intelCpu = new IntelCpu;
     VideoCard* intelCard = new IntelVideoCard;
     Memory* memory = new IntelMemory;
    //创建第一台电脑
     cout << "第一台电脑开始工作" << endl;
     Computer* computer1 = new Computer(intelCpu, intelCard, memory);
     computer1->work();
     delete computer1;
    //创建第二台电脑
     cout << "第二台电脑开始工作" << endl;
     Computer* computer2 = new Computer(new LenovoCPU ,new LenovoVideoCard, new LenovoMemory);
     computer2->work();
     delete computer2;
    //创建第三台电脑
     cout << "第三台电脑开始工作" << endl;
     Computer* computer3 = new Computer(new LenovoCPU, new IntelVideoCard, new LenovoMemory);
     computer3->work();
     delete computer3;
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
22.c++文件操作
 //程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放
 //通过文件可以将数据持久化
 //c++中对文件操作需要包含头文件<fstream>
 //文本文件:
 //1.文本文件           文件以文本的ASCII码形式存储在计算机中
 //2.二进制文件       文件以文本形式存储在计算机中,用户一般不能直接读懂他们。
 //操作文件三大类:1.ofstream:写操作        2.ifstream:读操作          3.fstream:读写操作
 //文件打开方式:
 //打开方式                        解释
 //ios::in                            为读文件而打开文件
 //ios::out                         为写文件而打开文件
 //ios::ate                          初始位置:文件尾
 //ios::app                         追加方式写文件
 //ios::trunc                       如果文件存在先删除,再创建
 //ios::binary                     二进制方式
 //注意:文件打开方式可以配合使用,利用|操作符  (eg:二进制方式写文件   ios::binary | ios::out)
//22.1文本文件-写文件
 #include<iostream>
 using namespace std;
 #include<fstream>//1.包含头文件:#include<fstream>
//文本文件写文件
 void test01() {
    //2.创建流对象:ofstream ofs;
     ofstream ofs;
    //3.打开文件:ofs.open("文件路径",打开方式);
     ofs.open("test.txt", ios::out);
    //4.写数据:ofs<<"写入的数据";
     ofs << "姓名:张三" << endl;
     ofs << "性别:男" << endl;
     ofs << "年龄:18" << endl;
    //5.关闭文件:ofs.close();
     ofs.close();
 }
int main(){
    test01();
     system("pause");
     return 0;
 }
//22.2文本文件-读文件
 #include<iostream>
 using namespace std;
 #include<fstream>
 #include<string>
//读文件
 void test01() {
     //创建流对象
     ifstream ifs;
     //打开文件,判断是否打开成功
     ifs.open("test.txt",ios::in);
     if (!ifs.is_open()) {
         cout << "文本打开失败" << endl;
         return;
     }
     //读数据
     //第一种:
     /*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 file
         cout << c;
     }
    //关闭文件
     ifs.close();
 }
int main(){
    test01();
     system("pause");
     return 0;
 }
//22.3二进制文件-写文件
 #include<iostream>
 using namespace std;
 #include<fstream>//1.包含头文件
 #include<string>
class Person {
 public:
     char m_Name[64];//姓名
     int m_Age;//年龄
 };
void test01() {
     //2.创建输出流对象
     ofstream ofs;
     //3.打开文件
     ofs.open("person.txt", ios::out | ios::binary);
     //4.写文件
     Person p = { "张三",18 };
     ofs.write((const char *) &p,sizeof(Person));
     //5.关闭文件
     ofs.close();
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//22.4二进制文件-读操作
 #include<iostream>
 using namespace std;
 #include<fstream>//1.包含头文件
class Person {
 public:
     char m_Name[64];//姓名
     int m_Age;//年龄
 };
void test01() {
     //2.创建流对象
     ifstream ifs;
     //3.打开文件  判断文件是否打开成功
     ifs.open("person.txt",ios::in|ios::binary);
     if (!ifs.is_open()) {
         cout << "文件打开失败" << endl;
         return;
     }
     //4.读文件
     Person p;
     ifs.read((char *) & p,sizeof(Person));
     cout << "姓名:" << p.m_Name << "   年龄:" << p.m_Age << endl;
     //关闭文件
     ifs.close();
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
23.模板
 //模板不可以直接使用,他只是一个框架
 //模板的通用并不是万能的
 //模板的目的是为了提高复用性,将类型参数化
//23.1函数模板
 //语法:template<typename T>
 //函数声明或定义
 //函数模板注意事项
 #include<iostream>
 using namespace std;
//函数模板
 template<typename T>//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错,T是一个通用数据类型
 void mySwap(T &a,T &b) {
     T temp = a;
     a = b;
     b = temp;
 }
void test01() {
     int a = 10;
     int b = 20;
    //两种方式使用模板:
     //1.自动类型推导
     //mySwap(a, b); 
     //2.显示指定类型
     mySwap<int>(a, b);
    cout << "a = " << a << endl;
     cout << "b = " << b << endl;
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//23.2普通函数与函数模板的区别
 #include<iostream>
 using namespace std;
//普通函数
 int myAdd(int a, int b) {
     return a + b;
 }
//函数模板
 template<typename T>
 T myAdd01(T a,T b) {
     return a + b;
 }
void test01() {
    int a = 10;
     char c = 'c';
     //1.普通函数调用时可以发生自动类型转换
     cout << myAdd(a, c) << endl;//109
     //2.函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换
     //自动类型推导
     //cout << myAdd01(a, c) << endl;
     //3.如果利用显示指定类型的方式,可以发生隐式类型转换
     //显示指定类型
     myAdd01<int>(a, c);//109
}
int main() {
    test01();
     system("pause");
     return 0;
 }
//23.3普通函数与函数模板的调用规则
 //1.如果函数模板和普通函数都可以实现,优先调用普通函数
 //2.可以通过空横板列表来强制调用函数模板
 //3.函数模板也可以发生重载
 //4.如果函数模板可以产生更好的匹配,优先调用函数模板
 #include<iostream>
 using namespace std;
//普通函数
 void myPrint(int a, int b)
 {
     cout << "调用的普通函数" << endl;
 }
template<typename T>
 void myPrint(T a,T b) {
     cout << "调用的模板" << endl;
 }
template<typename T>
 void myPrint(T a, T b,T c) {
     cout << "调用重载的模板" << endl;
 }
void test01() {
     int a = 10;
     int b = 20;
     //myPrint(a, b);//调用的普通函数
     //通过空横板列表来强制调用函数模板
     //myPrint<>(a, b);//调用的模板
     //myPrint(a, b, 100);//调用重载的模板
     //如果函数模板可以产生更好的匹配,优先调用函数模板
     char c1 = 'a';
     char c2 = 'b';
     myPrint(c1, c2);//调用的模板
}
int main() {
test01();
    system("pause");
     return 0;
 }
//23.4模板的局限性
 //1.利用具体化的模板,可以解决自定义类型的通用化
 //2.学习模板并不是为了写模板,而是在STL能够运用系统提供的模板
 #include<iostream>
 using namespace std;
//模板局限性
 //模板并不是万能的,有些特定数据类型,需要用具体化方式做特殊实现
class Person {
 public:
     Person(string name, int age) {
         this->m_Age = age;
         this->m_Name = name;
     }
    string m_Name;
     int m_Age;
 };
//对比两个数据是否相等函数
 template<typename T>
 bool myCompare(T &a,T &b) {
     if (a == b) {
         return true;
     }
     else {
         return false;
     }
 }
//利用具体化的版本实现代码,具体化优先调用
 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 test01() {
     Person p1("Tom", 18);
     Person p2("Tom", 18);
     bool ret = myCompare(p1, p2);
     if (ret) {
         cout << "p1 == p2" << endl;
     }
     else {
         cout << "p1 != p1" << endl;
     }
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//23.5类模板语法
 #include<iostream>
 using namespace std;
 #include<string>
//类模板
 template<class NameType,class AgeType>
 class Person {
 public:
     Person(NameType name, AgeType age) {
         this->m_Name = name;
         this->m_Age = age;
     }
    void showPerson() {
         cout << "name:" << this->m_Name << "  age:" << this->m_Age << endl;
     }
    NameType m_Name;
     AgeType m_Age;
 };
void test01() {
     Person<string, int> p1("孙悟空", 999);
     p1.showPerson();
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//23.6类模板与函数模板区别
 #include<iostream>
 using namespace std;
 #include<string>
//类模板
 template<class NameType,class AgeType = int>//2.类模板在模板模板参数列表中可以有默认参数
 class Person {
 public:
     Person(NameType name, AgeType age) {
         this->m_Name = name;
         this->m_Age = age;
     }
    void showPerson() {
         cout << "name:" << this->m_Name << "  age:" << this->m_Age << endl;
     }
    NameType m_Name;
     AgeType m_Age;
 };
 //1.类模板没有自动类型推导的使用方式
 void test01() {
     //Person p("孙悟空", 1000);//错误的,无法用自动类型推导
     Person<string,int>p1("孙悟空", 1000);//正确的,只能用显示指定类型
     p1.showPerson();
 }
void test02() {
     Person<string>p2("猪八戒", 999);
     p2.showPerson();
 }
int main() {
    test01();
     test02();
     system("pause");
     return 0;
 }
//23.7类模板中成员函数创建时机
 //普通类中的成员函数一开始就可以创建
 //类模板中的成员函数在调用时才可以创建
 #include<iostream>
 using namespace std;
class Person1 {
 public:
     void showPerson1() {
         cout << "Person1 show" << endl;
     }
 };
class Person2 {
 public:
     void showPerson2() {
         cout << "Person2 show" << endl;
     }
 };
 template<class T>
 class Myclass {
 public:
     T obj;
     //类模板中的成员函数,并不是一开始就创建的,而是在模板调用是在生成
     void func1() { obj.showPerson1(); }
     void func2() { obj.showPerson2(); }
};
void test01() {
     Myclass<Person1> m;
m.func1();
    //m.func2();//编译会出错,说明函数会调用才会去创建成员函数
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//23.8类模板对象做函数参数
 //1.指定传入的类型--------直接显示对象的数据类型
 //2.参数模板化       --------将对象中的参数变为模板进行传递
 //3.整个类模板化   --------将这个对象类型模板进行传递
 #include <iostream>
 using namespace std;
 #include<string>
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 test01() {
     Person<string, int>p("孙悟空", 100);
     printPerson1(p);
 }
//2.参数模板化
 template <class T1, class T2>
 void printPerson2(Person<T1, T2>& p1) {
     p1.showPerson();
     //查看模板推出的类型:
     cout << "T1的类型为:" << typeid(T1).name() << endl;
     cout << "T2的类型为:" << typeid(T2).name() << endl;
 }
void test02() {
     Person<string, int>p1("猪八戒", 90);
     printPerson2(p1);
 }
//3.整个类模板化
 template<class T>
 void printPerson3(T &p) {
     p.showPerson();
     cout << "T的数据类型为:" << typeid(p).name() << endl;
 }
void test03(){
     Person<string, int>p("唐僧", 30);
     printPerson3(p);
 }
int main() {
    //test01();
     //test02();
     test03();
    system("pause");
     return 0;
 }
//23.9类模板与继承
 //1.当子类继承的父类是一个类模板时,子类在声明的时候,要指出父类中T的类型
 //2.如果不指定,编译器无法给子类分配内存
 //3.如果想灵活指定父类中T的类型,子类也需要变为类模板
 #include<iostream>
 using namespace std;
//类模板与继承
 template<class T>
 class Base {
     T m;
 };
//class Son :public Base//错误,必须要知道父类中的T类型,才能继承给子类
 class Son:public Base<int> {
};
void test01() {
     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 test02() {
     Son2<int, char>S2;
 }
int main() {
    //test01();
     test02();
     system("pause");
     return 0;
 }
//23.10类模板成员函数类外实现
 #include<iostream>
 using namespace std;
 #include<string>
template<class T1,class T2>
 class Person {
 public:
     Person(T1 name, T2 age);
     void showPerson();
    T1 m_Name;
     T2 m_Age;
 };
//构造函数类外实现
 template<class T1,class T2>
 Person<T1, T2>::Person(T1 name, T2 age) {
     this->m_Name = name;
     this->m_Age = age;
 }
//成员函数类外实现
 template<class T1, class T2>
 void Person<T1,T2>::showPerson() {
     cout << "姓名:" << this->m_Name << "  年龄:" << this->m_Age << endl;
 }
void test01() {
     Person<string, int> P("Tom", 20);
     P.showPerson();
 }
int main() {
    test01();
     system("pause");
     return 0;
 }
//23.11类模板分文件编写
 //类模板中成员函数创建时机,是在调用阶段,导致分文件编写时链接不到
 //第一种解决方式,直接包含源文件
 //Person.h
 #pragma once
 #include<iostream>
 using namespace std;
#include <string>
template<class T1, class T2>
 class Person {
 public:
     Person(T1 name, T2 age);
     void showPerson();
    T1 m_Name;
     T2 m_Age;
 };
//Person.cpp
 #include "Person.h"
template<class T1, class T2>
 Person<T1, T2>::Person(T1 name, T2 age) {
     this->m_Name = name;
     this->m_Age = age;
 }
template<class T1, class T2>
 void Person<T1, T2>::showPerson() {
     cout << "姓名为:" << this->m_Name << "  年龄为:" << this->m_Age << endl;
 }
//类模板分文件编写.cpp
 #include <iostream>
 using namespace std;
 #include "Person.cpp"
void test01() {
     Person <string, int> P("Tom", 20);
     P.showPerson();
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//第二种解决方式,将.h和.cpp中的内容写到一起,将后缀名改为.hpp文件
 //Person.hpp
 #pragma once
 #include<iostream>
 using namespace std;
#include <string>
template<class T1, class T2>
 class Person {
 public:
     Person(T1 name, T2 age);
     void showPerson();
    T1 m_Name;
     T2 m_Age;
 };
template<class T1, class T2>
 Person<T1, T2>::Person(T1 name, T2 age) {
     this->m_Name = name;
     this->m_Age = age;
 }
template<class T1, class T2>
 void Person<T1, T2>::showPerson() {
     cout << "姓名为:" << this->m_Name << "  年龄为:" << this->m_Age << endl;
 }
//类模板分文件编写.cpp
 #include <iostream>
 using namespace std;
 #include "Person.hpp"
//第二种解决方式,将.h和.cpp中的内容写到一起,将后缀名改为.hpp文件
 void test01() {
     Person <string, int> P("Tom", 20);
     P.showPerson();
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//23.12类模板与友元
 //全局函数类内实现,直接在类内声明友元即可
 //全局函数类外实现,需要提前让编译器知道全局函数的存在
 #include<iostream>
 using namespace std;
 #include<string>
//提前让编译器知道Person类存在
 template<class T1,class T2>
 class 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 test01() {//全局函数,类内实现
     Person<string, int>p("Tom", 20);
     printPerson(p);
 }
void test02() {//全局函数,类外实现
     Person<string, int>p("Jerry", 20);
     printPerson2(p);
 }
int main() {
    test01();
     test02();
    system("pause");
     return 0;
 }
//23.13案例
 //MyArray.hpp
 #pragma once
 #include <iostream>
 using namespace std;
 #include <string>
template<class T>
 class MyArray {
 public:
    //有参构造
     MyArray(int capicity) {
         //cout << "Myarray有参构造调用" << endl;
         this->m_Capacity = capicity;
         this->m_Size = 0;
         this->pAddress = new T[this->m_Capacity];
     }
     
     //拷贝构造
     MyArray(const MyArray& arr) {
        //cout << "Myarray拷贝构造调用" << endl;
         this->m_Capacity = arr.m_Capacity;
         this->m_Size = arr.m_Size;
         //this->pAddress = arr.pAddress;
         
         //深拷贝
         this->pAddress = new T[arr.m_Capacity];
         
         //将arr中的数据都拷贝过来
         for(int i = 0; i < this->m_Size; i++) {
             this->pAddress[i] = arr.pAddress[i];
         }
}
    //operator= 防止浅拷贝问题
     MyArray& operator=(const MyArray& arr) {
         //cout << "Myarray  的 oprator=调用" << endl;
         //先判断原来堆区是否有数据,如果有先释放
         if (this->pAddress != NULL) {
             delete[] this->pAddress;
             this->pAddress = NULL;
             this->m_Capacity = 0;
             this->m_Size = 0;
         }
        //深拷贝
         this->m_Capacity = arr.m_Capacity;
         this->m_Size = arr.m_Size;
         this->pAddress = arr.pAddress;
         for (int i = 0; i < arr.m_Size; i++) {
             this->pAddress[i] = arr.pAddress[i];
         }
        return *this;
     }
    //尾插法
     void Push_Back(const T & val) {
         //判断容量是否等于大小
         if (this->m_Capacity == this->m_Size) {
             return;
         }
         this->pAddress[this->m_Size] = val;  //在数组末尾插入数据
         this->m_Size++;  //更新数组大小
     }
    //尾删法
     void Pop_Back() {
         //让用户访问不到最后一个元素,即为尾删,逻辑删除
         if (this->m_Size == 0) {
             return;
         }
         this->m_Size--;
     }
    //通过下标方式访问数组中的元素
     T& operator[](int index) {
         return this->pAddress[index];
     }
    //返回数组容量
     int getCapacity() {
         return this->m_Capacity;
     }
    //返回数组大小
     int getSize() {
         return this->m_Size;
     }
    //析构函数
     ~MyArray() {
         if (this->pAddress != NULL) {
             //cout << "Myarray析构函数调用" << endl;
                 delete[] this->pAddress;
             this->pAddress = NULL;
         }
     }
 private:
T *pAddress;//指针指向堆区开辟的真实数组
int m_Capacity;//数组容量
    int m_Size;//数组大小
 };
//c++.cpp
 #include <iostream>
 using namespace std;
 #include "MyArray.hpp"
 #include <string>
void printIntArray(MyArray <int>& arr) {
     for (int i = 0; i < arr.getSize(); i++) {
         cout << arr[i] << endl;
     }
 }
void test01() {
     /*MyArray<int> arr1(5);
     MyArray<int> arr2(arr1);
     MyArray<int> arr3(100);
     arr3 = arr1;*/
     MyArray <int>arr1(5);
    for (int i = 0; i < 5; i++) {
         //利用尾插法想数组中插入数据
         arr1.Push_Back(i);
     }
    cout << "arr1的打印输出为:" << endl;
     printIntArray(arr1);
    cout << "arr1的容量为:" << arr1.getCapacity() << endl;
     cout << "arr1的大小为:" << arr1.getSize() << endl;
    MyArray <int>arr2(arr1);
     cout << "arr2的打印输出为:" << endl;
     printIntArray(arr2);
    //尾删
     arr2.Pop_Back();
     cout << "arr2尾删后:" << endl;
     cout << "arr2的容量为:" << arr1.getCapacity() << endl;
     cout << "arr2的大小为:" << arr1.getSize() << endl;
}
//测试自定义数据类型
 class Person {
 public:
     Person() {};
    Person(string name, int age) {
         this->m_Name = name;
         this->m_Age = age;
     }
    string m_Name;
     int m_Age;
 };
void printPersonArray(MyArray<Person>& arr) {
     for (int i = 0; i < arr.getSize(); i++) {
         cout << "姓名:" << arr[i].m_Name << "  年龄:" << arr[i].m_Age << endl;
     }
 }
void  test02() {
     MyArray<Person> arr(10);
    Person p1("孙悟空", 999);
     Person p2("韩信", 30);
     Person p3("妲己", 28);
     Person p4("赵云", 50);
     Person p5("安琪拉", 27);
    //将数据插入到数组中
     arr.Push_Back(p1);
     arr.Push_Back(p2);
     arr.Push_Back(p3);
     arr.Push_Back(p4);
     arr.Push_Back(p5);
    //打印数组
     printPersonArray(arr);
    //输出容量
     cout << "arr的容量为:" << arr.getCapacity() << endl;
     //输出大小
     cout << "arr的大小为:" << arr.getSize() << endl;
 }
int main() {
    /*test01();*/
     test02();
     system("pause");
     return 0;
 }
24. STL
 //STL(Standard Template Library,标准模板库)
 //STL(广分):容器(container),算法 (algorithm),迭代器(iterator)
 //容器和算法之间通过迭代器进行无缝衔接
 //STL几乎所有的代码都采用了模板类或模板函数
 //STL(细分):容器,算法,迭代器,仿函数,适配器,空间配置器
 //24.1
 //容器:各种数据结构-----如:vector,list,deque,set,map等
 //算法:各种常用常用算法------如:sort,find,copy,for_rach等
 //迭代器:扮演了容器与算法之间的胶合剂
 //仿函数:行为类似函数,可作为算法的某种策略
 //适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
 //空间配置器:负责空间的配置与管理
 //
 //容器分为序列式容器和关联式容器
 //序列式容器:强调值的排序,序列式容器中每个元素均有固定的位置
 //关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
 //
 //算法(Algorithms)分为质变算法和非质变算法
 //质变算法:运算过程中更改区间内的元素的内容,例如:拷贝,替换,删除
 //非质变算法:运算过程中不会更改区间的元素内容,例如:查找,计数,遍历,寻找极值
 //
 //迭代器:提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的的内部表达方式
 //每个容器都有自己专属的迭代器
| 种类 | 功能 | 支持运算 | 
| 输入迭代器 | 对数据的只读访问 | 只读,支持++,==,!= | 
| 输出迭代器 | 对数据的只写访问 | 只写,支持++ | 
| 前向迭代器 | 读写操作,并能向前推进迭代器 | 读写,支持++,==,!= | 
| 双向迭代器 | 读写操作,并能向前和向后操作 | 读写,支持++,-- | 
| 随机访问迭代器 | 读写操作,可以以跳跃的方式访问随机任意数据,功能最强大 | 读写,支持++,--,[n],-n,<,<=,>,>= | 
25.容器
//25.1vector容器
 //25.1.1vector存放内置数据类型
 //算法:for_each         迭代器:vector<int>::iterator
 #include<iostream>
 using namespace std;
 #include <vector>
 #include<algorithm>//标准算法头文件
void myPrint(int val) {
     cout << val << endl;
 }
void test01() {
     //创建vector容器
     vector<int> v;
    //往容器中插入数据
     v.push_back(10);
     v.push_back(20);
     v.push_back(30);
    通过迭代器访问容器中的数据
     //vector<int>::iterator itBegin = v.begin();//起始迭代器,指向容器中第一个迭代器
     //vector<int>::iterator itEnd = v.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() {
     test01();
     system("pause");
     return 0;
 }
//25.1.2vector存放自定义数据类型
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<string>
class Person {
 public:
     Person(string name, int age) {
         this->m_Name = name;
         this->m_Age = age;
     }
     string m_Name;
     int m_Age;
 };
void test01() {
     vector<Person>v;
    Person p1("aaa", 10);
     Person p2("bbb", 20);
     Person p3("ccc", 30);
     Person p4("ddd", 40);
     Person p5("eee", 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 test02() {
     vector<Person*>v;
    Person p1("aaa", 10);
     Person p2("bbb", 20);
     Person p3("ccc", 30);
     Person p4("ddd", 40);
     Person p5("eee", 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() {
     //test01();
     test02();
     system("pause");
     return 0;
 }
//25.1.3vector容器嵌套容器
 #include<iostream>
 using namespace std;
 #include<vector>
void test01() {
     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() {
test01();
    system("pause");
     return 0;
 }
//25.2string
 //char*是一个指针
 //string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器
 //特点:string是一个类,类内部封装了很多成员方法
 //eg:find(),copy(),delete(),replace(),insert().
 //string管理了char*所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责
//25.2.1string构造函数
 //string();                               //创建空字符串
 //string(const char* s);        //使用字符串s初始化 
 //string(const string& str); //使用一个string对象初始化另一个string对象
 //string(int,char c);              //使用n个字符串c初始化  
 #include<iostream>
 using namespace std;
 #include<string>
void test01() {
     string s1;//默认构造
    const char* str = "hello world";
     string s2(str);
     cout << "s2 = " << s2 << endl;
    string s3(s2);
     cout << "s3 = " << s3 << endl;
    string s4(10, 'a');
     cout << "s4 = " << s4 << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.2.2string赋值操作
 // string& operator=(const char* s);          //char*类型字符串赋值给当前的字符串
 // string& operator=(const string &s);     //把字符串s赋值给当前的字符串
 // string& operator=(char c);                     //字符赋值给当前的字符串
 // string& assign(const char *s);               //把字符串s赋值给当前的字符串
 // string& assign(const char *s,int n)       //把字符串s的前n个字符付给当前的字符串
 // string& assign(const string &s);          //把字符串s赋值给当前字符串
 // string& assign(int n,char c);                  //用n个字符c赋值给当前字符串
 #include<iostream>
 using namespace std;
 #include<string>
void test01() {
     string str1;
     str1 = "HelloWorld";
     cout << "str1 = " << str1 << endl;
    string str2;
     str2 = str1;
     cout << "str2 = " << str2 << endl;
    string str3;
     str3 = 'a';
     cout << "str3 = " << str3 << endl;
    string str4;
     str4.assign("hello C++");
     cout << "str4 = " << str4 << endl;
    string str5;
     str5.assign("hello C++", 5);
     cout << "str5 = " << str5 << endl;
    string str6;
     str6.assign(str5);
     cout << "str6 = " << str6 << endl;
    string str7;
     str7.assign(3, '6');
     cout << "str7 = " << str7 << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.2.3string字符串拼接
 // string& oparator+=(const char* str);            //重载+=操作符
 // string& operator+=(const char c);               //重载+=操作符
 // string& operator+=(const string& str);          //重载+=操作符
 // string& append(const char *s);                  //把字符串s连接到当前字符串结尾
 // string& append(const char *s,int n);            //把字符串s的前n个字符连接到当前字符串结尾
 // string& append(const string &s);                //同operator+=(const string& s);
 // string& append(const string &s,int pos,int n);  //字符串s中从pos开始的n个字符连接到字符串结尾
 #include<iostream>
 using namespace std;
 #include<string>
void test01() {
     string str1 = "我";
    str1 += "爱玩游戏";
     cout << "str1 = " << str1 << endl;
    str1 += ':';
     cout << "str1 = " << str1 << endl;
    string str2 = "LOL DNF";
     str1 += str2;
     cout << "str1 = " << str1 << endl;
    string str3 = "I";
     str3.append(" love ");
     cout << "str3 = " << str3 << endl;
    str3.append("game abcde", 4);
     cout << "str3 = " << str3 << endl;
    /*str3.append(str2);
     cout << "str3 = " << str3 << endl;*/
    //str3.append(str2, 0, 3);//只截取到LOL
     //cout << "str3 = " << str3 << endl;
    str3.append(str2, 4, 3);//只截取到DNF,参数2从哪个位置截取,参数三截取字符个数
     cout << "str3 = " << str3 << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.2.4string查找和替换
 //查找:查找指定字符串是否存在
 //替换:在指定的位置替换字符串
 // int find(const string& str,int pos = 0)const;          //查找str第一次出现的位置,从pos开始查找
 // int find(const char* s,int pos = 0)const;                 //查找s第一次出现位置,从pos开始查找
 // int find(const char* s,int pos,int n)const;               //从pos位置查找s的前n个字符第一次位置
 // int find(const char c,int pos = 0)const;                   //查找字符c第一次出现位置
 // int rfind(const string& str,int pos = npos)const;  //查找str最后一次位置,从pos开始查找
 // int rfind(const char* s,int pos,int n)const;             //查找s最后一次出现的位置,从pos开始查找
 // int rfind(const char* s,int pos,int n)const;             //从pos查找s的前n个字符最后一次位置
 // int rfind(const char c,int pos = 0)const;                 //查找字符c最后一次出现位置
 // string& replace(int pos,int n,const string& str);   //替换从pos开始n个字符为字符串str
 // string& replace(int pos,int n,const char* s);          //替换从pos开始的n个字符为字符串s;
 #include<iostream>
 using namespace std;
 #include<string>
//1.查找
 void test01() {
     string str1 = "abcdefgde";
    int pos = str1.find("de");//3
     if (pos == -1) {
         cout << "未找到字符串" << endl;
     }
     else {
         cout << "pos = " << pos << endl;
     }
    //rfind和find区别:rfind从右往左查找,find从左往右查找
     pos = str1.rfind("de");
     cout << "pos = " << pos << endl;//7
}
//2.替换
 void test02() {
     string str1 = "abcdefg";
    str1.replace(1, 3, "1111");
     cout << "str1 = " << str1 << endl;//a1111efg
 }
int main() {
    //test01();
     test02();
    system("pause");
     return 0;
 }
//25.2.5字符串比较
 //字符串比较是按字符的ASCII码进行对比
 //int compare(const string &s)  const;//与字符串比较
 //int compare(const char *s) const;    //与字符串比较
 #include<iostream>
 using namespace std;
 #include<string>
void test01() {
     string str1 = "hello";
     string str2 = "xello";
    if (str1.compare(str2) == 0) {
         cout << "str1 等于 str2" << endl;
     }
     else if(str1.compare(str2) > 0){
         cout << "str1 大于 str2" << endl;
     }
     else {
         cout << "str1 小于 str2" << endl;
     }
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.2.6string字符串存取
 //char& operator[](int n);   //通过[]方式取字符
 //char& at(int n);                  //通过at方法获取字符
 #include<iostream>
 using namespace std;
 #include<string>
void test01() {
     string str = "hello";
    //cout << "str = " << str << endl;
     
     //1.通过 [ ] 访问单个字符
     for (int i = 0; i < str.size(); i++) {
         cout << str[i] << " ";
     }
     cout << endl;
    //2.通过at访问单个字符
     for(int i = 0; i < str.size(); i++) {
         cout << str.at(i) << " ";
     }
     cout << endl;
    //修改单个字符
     str[0] = 'x';
     cout << "str = " << str << endl;//xello
    str.at(1) = 'x';
     cout << "str = " << str << endl;//xxllo
}
int main() {
test01();
    system("pause");
     return 0;
 }
//25.2.7string插入和删除
 //string& int(int pos,const char* s);                            //插入字符串
 //string& insert(int pos,const string& str);                //插入字符串
 //string& insert(int pos,int n,char c);                           //在指定位置插入n个字符c
 //string& erase(int pos,int n = npos);                         //删除从Pos开始的n个字符
 #include<iostream>
 using namespace std;
 #include<string>
void test01() {
     string str = "hello";
    //插入
     str.insert(1, "111");
     cout << "str = " << str << endl;//h111ello
    //删除
     str.erase(1, 3);
     cout << "str = " << str << endl;//hello
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.2.8string子串
 //string substr(int pos = 0,int n = npos) const;//返回由pos开始的n个字符组成的字符串
 #include<iostream>
 using namespace std;
 #include<string>
void test01() {
     string str = "abcedf";
string subStr = str.substr(1, 3);
    cout << "subStr = " << subStr << endl;//bce
 }
void test02() {
     string email = "zhangsan@sina.com";
    //从邮件地址中获取用户名信息
     int pos = email.find("@");
     string usrName = email.substr(0, pos);
    cout << usrName << endl;
 }
int main() {
    // test01();
     test02();
    system("pause");
     return 0;
 }
//25.3vector容器
 //功能:vector数据结构和数组非常相似,也称为单端数组
 //区别:数组是静态空间,而vector可以动态扩展
 //动态扩展:并不是在原空间之后继续接新空间,而是找更大的内存空间,然后将数据拷贝新空间,释放原空间
 //vector容器的迭代器是支持随机访问的迭代器
 //vector<T> v;                                //采用模板实现类实现,默认构造函数
 //vector(v.begin(),v.end());           //将v[begin(),end())区间中的元素拷贝给自身
 //vector(n,elem);                           //构造函数将n个elem拷贝给自身
 //vector(const vector &vec);       //拷贝构造函数
//25.3.1vector构造函数
 #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 test01() {
     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);
     printVector(v3);
    //拷贝构造
     vector<int>v4(v3);
     printVector(v4);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.3.2vector赋值操作
 //vector& operator=(const vector &vec);//重载等号操作符
 //assign(beg,end);             //将(beg,end)区间中的数据拷贝赋值给自身
 //assign(n,elem);               //将n个elem拷贝赋值给本身
 #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 test01() {
     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);
    //n个elem方式赋值
     vector<int>v4;
     v4.assign(10, 100);
     printVector(v4);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.3.3vector容器和大小
 //empty();                     //判断容器是否为空
 //capacity();                  //容器的容量
 //size();                          //返回容器中元素的个数
 //resize(int num);         //重新指定容器的长度为num,若容器变长,则默认值填充新位置。
                                        //如果容器变短,则末尾超出容器长度的元素被删除。
 //resize(int num,elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
                                         //如果容器变短,则末尾超出容器长度的元素被删除。
 #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 test01() {
     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);//利用重载版本,可以指定默认填充值,参数2
     printVector(v1);//如果重新指定的比原来长了,默认用0填充新的位置
    v1.resize(5);
     printVector(v1);//如果重新指定的比原来断了,超出部分会删除掉
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.3.4vector插入和删除                                                 
 //push_back(ele);                                                             //尾部插入元素ele
 //pop_back();                                                                   //删除最后一个元素
 //insert(const_iterator pos,ele);                                    //迭代器指向位置pos插入元素ele
 //insert(const_iterator pos,int count,ele);                   //迭代器指向位置pos插入count个元素ele
 //erase(const_iterator pos);                                          //删除迭代器指向的元素
 //erase(const_iterator start,const_iterator end);        //删除迭代器从start到end之间的元素
 //clear();                                                                           //删除容器中所有元素
 #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 test01(){
     vector<int>v1;
    //尾插
     v1.push_back(10);
     v1.push_back(20);
     v1.push_back(30);
     v1.push_back(40);
     v1.push_back(50);
    //遍历
     printVector(v1);
    //尾删
     v1.pop_back();
     printVector(v1);
    //插入  第一个参数是迭代器
     v1.insert(v1.begin(), 100);
     printVector(v1);
    v1.insert(v1.begin(), 2, 1000);
     printVector(v1);
    //删除
     v1.erase(v1.begin());
     printVector(v1);
    //清空
     //v1.erase(v1.begin(), v1.end());
     v1.clear();
     printVector(v1);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.3.5vector数据存取
 //at(int idx);                          //返回索引idx所指的数据
 //oparator[ ];                        //返回索引idx所指的数据
 //front();                                //返回容器中第一个数据元素
 //back();                                //返回容器中最后一个数据元素
 #include<iostream>
 using namespace std;
 #include<vector>
void test01() {
     vector<int> v1;
     for (int i = 0; i < 10; i++) {
         v1.push_back(i);
     }
    //利用[]方式访问数组中元素
     for (int i = 0; i < v1.size(); i++) {
         cout << v1[i] << " ";
     }
     cout << endl;
    //利用at方式访问元素
     for (int i = 0; i < v1.size(); i++) {
         cout << v1.at(i) << " ";
     }
     cout << endl;
    //获取第一个元素
     cout << "第一个元素为:" << v1.front() << endl;
    //获取最后一个元素
     cout << "最后一个元素为:" << v1.back() << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.3.6vector互换容器
 //swap(vec);       //将vec与本身的元素互换
 #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 test01() {
     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 test02() {
     vector<int>v;
     for (int i = 0; i < 100000; i++) {
         v.push_back(i);
     }
    cout << "v的容量为:" << v.capacity() << endl;
     cout << "v的大小为:" << v.size() << endl;
    v.resize(3);
     cout << "v的容量为:" << v.capacity() << endl;//138255
     cout << "v的大小为:" << v.size() << endl;//3
    //巧用swap可以收缩内存空间
     vector<int>(v).swap(v);
     //vector<int>(v)   匿名对象(执行完自动释放内存)     ||    .swap(v)   容器交换
     cout << "v的容量为:" << v.capacity() << endl;//3
     cout << "v的大小为:" << v.size() << endl;//3
 }
int main() {
    //test01();
     test02();
    system("pause");
     return 0;
 }
//25.3.7vector预留空间
 //功能:减少vector在动态扩展时的扩展次数
 //reverse(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问。
 #include<iostream>
 using namespace std;
 #include<vector>
void test01() {
     vector<int> v;
    //利用reserve预留空间
     v.reserve(10000);
    int num = 0;//统计开辟次数
     int* p = NULL;
     for (int i = 0; i < 100000; i++) {
         v.push_back(i);
         if (p != &v[0]) {
             p = &v[0];
             num++;
         }
     }
    cout << "num = " << num << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.4deque容器
 //功能:双端数组,可以对头端进行插入删除操作
 //deque与vector区别:
 //vector对于头部的插入删除效率低,数据量越大,效率越低
 //deque相对而言,对头部的插入删除速度会比vector快
 //vector访问元素时的速度会比deque快,这和两者内部实现有关
 //deque内部工作原理:
 //deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
 //中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
//25.4.1deque构造函数
 //deque<T> deq;                              //默认构造形式
 //deque(bug,end);                            //构造函数将[beg,end]区间中的元素拷贝给本身
 //deque(n,else);                                //构造函数将n个elem拷贝给本身
 //deque(const deque &deq);         //拷贝构造函数
 #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++) {
         //*it = 100;  容器中的数据不可修改
         cout << *it << " ";
     }
     cout << endl;
 }
void test01() {
     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);
    deque<int>d3(10, 100);
     printDeque(d3);
    deque<int>d4(d3);
     printDeque(d4);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.4.2deque赋值操作
 //deque& operator=(const deque &deq);             //重载等号操作符
 //assign(beg,end);                                                     //将[beg,end]区间中的数据拷贝赋值给本身
 //assign(n,else);                                                         //将n个elem拷贝赋值给本身
 #include<iostream>
 using namespace std;
 #include<deque>
void printDeque(deque<int> &d) {
     for (deque<int>::iterator it = d.begin(); it != d.end(); it++) {
         cout << *it << " ";
     }
     cout << endl;
 }
void test01() {
     deque<int>d1;
     for (int i = 0; i < 10; i++) {
         d1.push_back(i);
     }
     printDeque(d1);
    //operator=赋值
     deque<int>d2;
     d2 = d1;
     printDeque(d2);
    //assign赋值
     deque<int>d3;
     d3.assign(d1.begin(), d1.end());
     printDeque(d3);
    deque<int>d4;
     d4.assign(10, 100);
     printDeque(d4);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.4.3deque大小操作
 //deque.empty();                           //判断容器是否为空
 //deque.size();                               //返回容器中元素个数
 //deque.resize(num);                    //重新指定容器的长度为num,若容器变长,则以默认值填充新位置
                                                         //如果容器变短,则末尾超出容器长度的元素被删除
 //deque.resize(num,elem);          //重新指定容器的长度为num,若容器边长,则以elem值填充新位置
                                                         //如果容器变短,则末尾超出容器长度的元素杯删除
 #include<iostream>
 using namespace std;
 #include<deque>
void printDeque(deque<int> &d) {
     for (deque<int>::iterator it = d.begin(); it != d.end(); it++) {
         cout << *it << " ";
     }
     cout << endl;
 }
void test01() {
     deque<int>d1;
     for (int i = 0; i < 10; i++) {
         d1.push_back(i);
     }
     printDeque(d1);
    if (d1.empty()) {
         cout << "d1为空" << endl;
     }
     else {
         cout << "d1不为空" << endl;
         cout << "d1的大小为:" << d1.size() << endl;
         //deque没有容量的概念
     }
    //重新指定大小
     //d1.resize(15);
     d1.resize(15, 1);
     printDeque(d1);
    d1.resize(5);
     printDeque(d1);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.4.4deque插入和删除
 //两端插入操作:
 //push_back(elem);              //在容器尾部添加一个数据
 //push_front(elem);             //在容器头部插入一个数据
 //pop_back(elem);               //删除容器最后一个数据
 //pop_front();                       //删除容器第一个数据
 //指定位置操作:
 //insert(pos,elem);               //在pos位置插入一个elem元素的拷贝,返回新数据的位置
 //insert(pos,n,elem);            //在pos位置插入n个elem数据,无返回值
 //insert(pos,beg,end);         //在pos位置插入[beg,end]区间的数据,无返回值
 //clear();                                //清空容器的所有数据
 //erase(beg,end);                 //删除[beg,end]区间的数据,返回下一个数据的位置
 //erase(pos);                         //删除pos位置的数据,返回下一个数据的位置
 #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++) {
         cout << *it << " ";
     }
     cout << endl;
 }
void test01() {
     deque<int>d1;
    //尾插:
     d1.push_back(10);
     d1.push_back(20);
    //头插:
     d1.push_front(100);
     d1.push_front(200);
printDeque(d1);//200 100 10 20
    //尾删
     d1.pop_back();
     printDeque(d1);//200 100 10
    //头删
     d1.pop_front();
     printDeque(d1);//100 10
 }
void test02() {
     deque<int>d1;
     d1.push_back(10);
     d1.push_back(20);
     d1.push_front(100);
     d1.push_front(200);
printDeque(d1);//200 100 10 20
    //insert插入
     d1.insert(d1.begin(), 1000);
     printDeque(d1);//1000 200 100 10 20
    d1.insert(d1.begin(), 2, 10000);
     printDeque(d1);//10000 10000 1000 200 100 10 20
    //按照区间进行插入
     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);//1 2 3 10000 10000 1000 200 100 10 20
 }
void test03() {
     deque<int>d1;
     d1.push_back(10);
     d1.push_back(20);
     d1.push_front(100);
     d1.push_front(200);
    //删除
     deque<int>:: iterator it = d1.begin();
     it++;
     d1.erase(it);
     printDeque(d1);//200 10 20
    //按照区间方式删除
     //d1.erase(d1.begin(), d1.end());
     //清空
     d1.clear();
     printDeque(d1);
 }
int main() {
    //test01();
     //test02();
     test03();
    system("pause");
     return 0;
 }
//25.4.5deque容器数据存取
 #include<iostream>
 using namespace std;
 #include<deque>
void test01() {
     deque<int>d;
     d.push_back(10);
     d.push_back(20);
     d.push_back(30);
     d.push_front(100);
     d.push_front(200);
     d.push_front(300);
    //通过[]方式访问元素
     for (int i = 0; i < d.size(); i++) {
         cout << d[i] << " ";
     }
     cout << endl;
    //通过at方式访问元素
     for (int i = 0; i < d.size(); i++) {
         cout << d.at(i) << " ";
     }
     cout << endl;
    cout << "第一个元素为:" << d.front() << endl;
     cout << "最后一个元素为:" << d.back() << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.4.6deque排序
 #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++) {
         cout << *it << " ";
     }
     cout << endl;
 }
void test01() {
     deque<int>d;
     d.push_back(10);
     d.push_back(20);
     d.push_back(30);
     d.push_front(100);
     d.push_front(200);
     d.push_front(300);
printDeque(d);
    //排序   默认排序规则是从小到大,即升序
         //对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序
         //vector容器也可以利用sort进行排序
     sort(d.begin(),d.end());
     cout << "排序后:" << endl;
     printDeque(d);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.5案例评委打分
 //描述:有5名选手,选手ABCDE,10个评委分别对每一个选手打分,去除最高分,去除评委中最低分,取平均分
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<string>
 #include<deque>
 #include<algorithm>
 #include<ctime>
class Person {
 public:
     Person(string name, int score) {
         this->m_Name = name;
         this->m_Score = score;
     }
    string m_Name;//姓名
     int m_Score;//平均分
 };
void createPerson(vector<Person> &v) {
     string nameSeed = "ABCDE";
     for (int i = 0; i < 5; i++) {
         string name = "选手";
         name += nameSeed[i];
int score = 0;
Person p(name, score);
        //将创建的person对象
         v.push_back(p);
     }
 }
//打分
 void setScore(vector<Person>&v) {
     for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
         //将评委的分数放入到deque容器中
         deque<int>d;
         for (int i = 0; i < 10; i++) {
             int score = rand() % 41 + 60;  //60~100
             d.push_back(score);
         }
        /*cout << "选手:" << it->m_Name << "打分:" << endl;
         for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++) {
             cout << *dit << " ";
         }
         cout << endl;*/
        //排序
         sort(d.begin(),d.end());
        //去除最高和最低分
         d.pop_back();
         d.pop_front();
        //取平均分
         int sum = 0;
         for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++) {
             sum += *dit;   //累加每个评委的分数
         }
int avg = sum / d.size();
        //将平均分赋值给选手身上
         it->m_Score = avg;
     }
 }
void showScore(vector<Person>&p) {
     for (vector<Person>::iterator it = p.begin(); it != p.end(); it++) {
         cout << "姓名: " << it->m_Name << "  平均分: " << it->m_Score << endl;
     }
 }
int main() {
    //随机数种子
     srand((unsigned int)time(NULL));
    //1.创建5名选手
     vector<Person>v;  //存放选手容器
     createPerson(v);
    测试
     //for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
     //    cout << "姓名:" << (*it).m_Name << "分数:" << it->m_Score << endl;
     //}
     
     //2.给5名选手打分
     setScore(v);
     //3.显示最后得分
     showScore(v);
    system("pause");
     return 0;
 }
//25.6stack容器
 //stack是一种先进后出的数据结构,只有一个出口
 //栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为
 //栈中进入数据成为:入栈push
 //栈中弹出数据成为:出栈pop
//25.6.1stack常用接口
 //stack<T> stk;                                         //stack采用模板实现,stack对象的默认构造形式
 //stack(const stack &stk);                       //拷贝构造函数
 //stack& operator=(const stack &stk); //重载等号操作符
 //push(elem);            //向栈顶添加元素
 //pop();                      //从栈顶移除第一个元素
 //top();                       //返回栈顶元素
 //empty();                  //判断堆栈是否为空
 //size();                      //返回栈的大小
 #include<iostream>
 using namespace std;
 #include<stack>
void test01() {
     stack<int>s;
    //入栈:
     s.push(10);
     s.push(20);
     s.push(30);
     s.push(40);
cout << "栈的大小为:" << s.size() << endl;
    //只要栈不为空,查看栈顶,并且执行出栈操作
     while (!s.empty()) {
         //查看栈顶元素
         cout << "栈顶元素为:" << s.top() << endl;
        //出栈
         s.pop();
     }
    cout << "栈的大小为:" << s.size() << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.7queue容器
 //Queue是一种先进先出的数据结构,它只有两个出口
 //队列容器允许从一端新增元素,从另一端移除元素
 //队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为
 //队列中进数据称为--入队push
 //队列中出数据称为--出队pop
//25.7.1queue常用接口
 //queue<T> que;                               //queue采用模板实现,queue对象的默认构造形式
 //queue(const queue &que);           //拷贝构造函数
 //queue& operator=(const queue &que);           //重载等号操作符
 //push(elem);                   //往队尾添加元素
 //pop();                             //从对头移除第一个元素
 //back();                            //返回最后一个元素
 //front();                            //返回第一个元素
 //empty();                 //判断堆栈是否为空
 //size();                     // 返回栈的大小
 #include<iostream>
 using namespace std;
 #include<queue>
class Person {
 public:
     Person(string name,int age) {
         this->m_Name = name;
         this->m_Age = age;
     }
     string m_Name;
     int m_Age;
 };
void test01() {
     //创建队列
     queue<Person>q;
    //准备数据
     Person p1("唐僧", 30);
     Person p2("猪八戒", 900);
     Person p3("孙悟空", 800);
     Person p4("沙师弟", 800);
    //入队
     q.push(p1);
     q.push(p2);
     q.push(p3);
     q.push(p4);
cout << "队列的大小为:" << q.size() << endl;
    //判断只要队列不为空,查看对头,查看队尾,出队
     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() << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.8list容器
 //链表(list)是一种物理存储单元上非连续的存储单元,数据元素的逻辑顺序是通过链表中的指针链表实现的
 //链表的组成:链表由一系列节点组成
 //节点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
 //STL中的链表是一个双向循环链表
 //由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
 //list优点:
 //采用动态存储分配,不会造成内存浪费和溢出
 //链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
 //list缺点:
 //链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大
 //List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector容器是不成立的
//25.8.1list构造函数
 //list<T> lst;                              //list采用模板类实现对象的默认构造形式
 //list(beg,end);                         //构造函数将[beg,end)区间中的元素拷贝给本身
 //list(n,elem);                            //构造函数将n个elem拷贝给本身
 //list(const list &lst);               //拷贝构造函数
 #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 test01() {
     //创建list容器
     list<int>L1;
    //添加数据
     L1.push_back(10);
     L1.push_back(20);
     L1.push_back(30);
     L1.push_back(40);
    //遍历容器
     printList(L1);
    //区间方式构造
     list<int>L2(L1.begin(), L1.end());
     printList(L2);
    //拷贝构造
     list<int>L3(L2);
     printList(L3);
    //n个elem
     list<int>L4(10, 1000);
     printList(L4);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.8.2list容器赋值和交换
 //assign(beg,end);                                      //将[beg,end)区间中的数据拷贝赋值给本身
 //assign(n,elem);                                         //将n个elem拷贝赋值给本身
 //list& operator=(const list &list);           //重载等号操作符
 //swap(lst);                                                  //将lst与本身的元素互换
 #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 test01() {
     list<int>L1;
     L1.push_back(10);
     L1.push_back(20);
     L1.push_back(30);
     L1.push_back(40);
printList(L1);
    list<int>L2;
     //operator=赋值
     L2 = L1;
     printList(L2);
    list<int>L3;
     L3.assign(L2.begin(), L2.end());
     printList(L2);
    list<int>L4;
     L4.assign(10, 100);
     printList(L4);
 }
//交换
 void test02(){
     list<int>L1;
    L1.push_back(10);
     L1.push_back(20);
     L1.push_back(30);
     L1.push_back(40);
    list<int>L2;
     L2.assign(10, 100);
    cout << "交换前:" << endl;
     printList(L1);
     printList(L2);
    L1.swap(L2);
     cout << "交换后:" << endl;
     printList(L1);
     printList(L2);
}
int main() {
    //test01();
     test02();
    system("pause");
     return 0;
 }
//25.8.3list大小操作
 //size();                     //返回容器中元素的个数
 //empty();                 //判断容器是否为空
 //resize(num);                  //重新指定容器的长度为num,若容器变长,则以默认值填充新位置
                                           //如果容器变短,则末尾超过容器长度的元素被删除
 //resize(num,elem);        //重新指定容器的长度为num,若容器变长,则以elem值填充新位置
                                           //如果容器变短,则末尾超过容器长度的元素被删除  
 #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 test01() {
     list<int>L1;
     L1.push_back(10);
     L1.push_back(20);
     L1.push_back(30);
     L1.push_back(40);
printList(L1);
    //判断容器是否为空
     if (L1.empty()) {
         cout << "L1为空" << endl;
     }
     else {
         cout << "L1不为空" << endl;
         cout << "L1容器个数为:" << L1.size() << endl;
     }
    //重新指定大小
     L1.resize(10,10000);
     printList(L1);
    L1.resize(2);
     printList(L1);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.8.4list插入和删除
 //push_back(elem);               //在容器尾部加入一个元素
 //pop_back();                        //删除容器中最后一个元素
 //push_front(elem);              //在容器开头插入一个元素
 //pop_front();                        //在容器开头移除第一个元素
 //insert(pos,elem);                //在pos位置插入elem元素的拷贝,返回新数据的位置
 //insert(pos,n,elem);            //在pos位置插入n个elem的数据,无返回值
 //insert(pos,beg,end);         //在pos位置插入[beg,end]区间的数据,无返回值
 //clear();                                 //移除容器的所有数据
 //erase(beg,end);                 //删除[beg,end]区间的数据,返回下一个数据的位置
 //erase(pos);                         //删除pos位置的数据,返回下一个数据的位置
 //remove(elem);                   //删除容器中所有与elem值匹配的元素
 #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 test01() {
     list<int>L;
    //尾插
     L.push_back(10);
     L.push_back(20);
     L.push_back(30);
    //头插
     L.push_front(100);
     L.push_front(200);
     L.push_front(300);
printList(L);
    //尾删
     L.pop_back();
     printList(L);
    //头删
     L.pop_front();
     printList(L);
    //插入
     list<int>::iterator it = L.begin();
     L.insert(++it, 1000);
     printList(L);
    //删除
     it = L.begin();
     L.erase(++it);
     printList(L);
    //移除
     L.push_back(10000);
     L.push_back(10000);
     L.push_back(10000);
     L.push_back(10000);
     printList(L);
     L.remove(10000);
     printList(L);
    //清空
     L.clear();
     printList(L);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.8.5list数据存取
 //front();     //返回第一个元素
 //back();     //返回最后一个元素
 #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 test01() {
     list<int>L1;
     L1.push_back(10);
     L1.push_back(20);
     L1.push_back(30);
     L1.push_back(40);
//不可以用[]和at方式访问容器中的元素,因为list本质时链表,不是用连续线性空间存储数据
    cout << "第一个元素为:" << L1.front() << endl;
     cout << "最后一个元素为:" << L1.back() << endl;
     
     //验证迭代器是不支持随机访问的
     list<int>::iterator it = L1.begin();
     it++;//支持双向
     it--;
     //it = it + 1; //不支持随机访问
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.8.5list反序和排序
 //reverse();    //反转链表
 //sort();         //链表排序
 #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;
 }
void test01() {
     list<int>L1;
    L1.push_back(20);
     L1.push_back(10);
     L1.push_back(30);
     L1.push_back(50);
     L1.push_back(40);
    cout << "反转前:" << endl;
     printList(L1);
    //反转后:
     L1.reverse();
     cout << "反转后:" << endl;
     printList(L1);
}
bool myCompare(int v1,int v2) {
     return v1 > v2;
 }
//排序
 void test02() {
     list<int>L1;
    L1.push_back(20);
     L1.push_back(10);
     L1.push_back(30);
     L1.push_back(50);
     L1.push_back(40);
    cout << "排序前:" << endl;
     printList(L1);
    //所有不支持随机访问迭代器的容器,不可以用标准算法
     //不支持随机访问迭代器的容器,内部会提供对应一些算法
     //sort(L1.begin(), L1.end());
     L1.sort();//默认排序规则:从小到大,升序
     cout << "排序后:" << endl;
     printList(L1);
    L1.sort(myCompare);
     printList(L1);
 }
int main() {
    //test01();
     test02();
    system("pause");
     return 0;
 }
//25.8.6排序案例
 //案例描述:将Person自定义数据类型进行排序,Person中属性有姓名,年龄,身高
 //排序规则:按照年龄进行升序,如果年龄相同按照身高进行降序
 #include<iostream>
 using namespace std;
 #include<list>
 #include<string>
class Person {
 public:
     Person(string name,int age,int height) {
         this->m_Name = name;
         this->m_Age = age;
         this->m_Height = height;
     }
    string m_Name;   //姓名
     int m_Age;       //年龄
     int m_Height;    //身高
 };
//指定排序规则
 bool comparePerson(Person& p1, Person& p2) {
     //按照年龄 升序
     if (p1.m_Age == p2.m_Age) {
         return p1.m_Height > p2.m_Height;
     }
     return p1.m_Age < p2.m_Age;
 }
void test01() {
     list<Person>L;   //创建容器
    //准备数据
     Person p1("古月方源",35,175);
     Person p2("吴帅    ", 45, 180);
     Person p3("气海老祖", 45, 170);
     Person p4("战部渡  ", 30, 190);
     Person p5("李小白  ", 25, 160);
     Person p6("梦求真  ", 35, 200);
    //插入数据
     L.push_back(p1);
     L.push_back(p2);
     L.push_back(p3);
     L.push_back(p4);
     L.push_back(p5);
     L.push_back(p6);
    for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {
         cout << "姓名:" << (*it).m_Name << "年龄:" << (*it).m_Age << "身高:" << (*it).m_Height << endl;
     }
    //排序
     cout << "---------------------------" << endl;
     cout << "排序后:" << endl;
    L.sort(comparePerson);
     for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {
         cout << "姓名:" << (*it).m_Name << "年龄:" << (*it).m_Age << "身高:" << (*it).m_Height << endl;
     }
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.9set/multiset容器
 //所有元素都会在插入时自动被排序
 //set/multiset属于关联式容器,底层结构是用二叉树实现
 //区别:set不允许容器中有重复的元素,multiset允许容器中有重复的角色
//25.9.1set构造和赋值
 #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 test01() {
     set<int>s1;
    //插入数据 只有insert方式
     s1.insert(10);
     s1.insert(40);
     s1.insert(30);
     s1.insert(50);
     s1.insert(30);
    //遍历容器
     //set容器特点:所有元素插入的时候自动被排序
     //set容器不允许插入重复值
     printSet(s1);
    //拷贝构造
     set<int>s2(s1);
     printSet(s2);
    //赋值
     set<int>s3;
     s3 = s2;
     printSet(s3);
}
int main() {
test01();
    system("pause");
     return 0;
 }
//25.9.2set大小和交换
 #include<iostream>
 using namespace std;
 #include<set>
void printSet(set<int>s1) {
     for (set<int>::iterator it = s1.begin(); it != s1.end(); it++){
         cout << *it << " ";
     }
     cout << endl;
 }
void test01() {
     set<int>s1;
    //插入数据
     s1.insert(10);
     s1.insert(30);
     s1.insert(20);
     s1.insert(40);
    //打印数据
     printSet(s1);
    //判断是否为空
     if (s1.empty()) {
         cout << "s1为空" << endl;
     }
     else {
         cout << "s1不为空" << endl;
         cout << "s1的大小为:" << s1.size() << endl;
     }
 }
void test02() {
     set<int>s1;
    //插入数据
     s1.insert(10);
     s1.insert(30);
     s1.insert(20);
     s1.insert(40);
    set<int>s2;
     s2.insert(100);
     s2.insert(300);
     s2.insert(200);
     s2.insert(400);
    cout << "交换前:" << endl;
     printSet(s1);
     printSet(s2);
    cout << "交换后:" << endl;
     s1.swap(s2);
     printSet(s1);
     printSet(s2);
}
int main() {
    //test01();
     test02();
    system("pause");
     return 0;
 }
//25.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 test01() {
     set<int>s1;
    //插入
     s1.insert(10);
     s1.insert(30);
     s1.insert(20);
     s1.insert(40);
     
     //遍历
     printSet(s1);
    //删除
     s1.erase(s1.begin());
     printSet(s1);
    //删除重载版本
     s1.erase(30);
     printSet(s1);
    //清空
     s1.erase(s1.begin(),s1.end());
     printSet(s1);
     s1.clear();
     printSet(s1);
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.9.4set查找和统计
 //find(key);           //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
 //count(key);        //统计key的元素个数
 #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 test01() {
     //查找
     set<int>s1;
    //插入数据
     s1.insert(10);
     s1.insert(30);
     s1.insert(20);
     s1.insert(40);
set<int>::iterator pos = s1.find(30);
    if (pos != s1.end()) {
         cout << "找到元素:" << *pos << endl;
     }
     else {
         cout << "未找到元素" << endl;
     }
 }
//统计
 void test02() {
     set<int>s1;
    //插入数据
     s1.insert(10);
     s1.insert(30);
     s1.insert(20);
     s1.insert(40);
     s1.insert(30);
     s1.insert(30);
    //统计30的个数
     int num = s1.count(30);
     //对于set而言,统计结果要么是0,要么是1
     cout << "num = " << num << endl;
 }
int main() {
    //test01();
     test02();
    system("pause");
     return 0;
 }
//25.9.5set和multiset区别
 #include<iostream>
 using namespace std;
 #include<set>
void test01(){
     set<int>s;
    pair < set<int>::iterator,bool > ret = s.insert(10);
     
     if (ret.second) {
         cout << "第一次插入成功" << endl;
     }
     else {
         cout << "第一次插入失败" << endl;
     }
ret = s.insert(10);
    if (ret.second) {
         cout << "第二次插入成功" << endl;
     }
     else {
         cout << "第二次插入失败" << endl;
     }
    multiset<int>ms;
     //允许插入重复值
     ms.insert(10);
     ms.insert(10);
     ms.insert(10);
     ms.insert(10);
    for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) {
         cout << *it << " ";
     }
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.9.6pair队组创建
 //pair<type,type> p(value1,value2);
 //pair<type,type> p = make_pair(value1,value2);
 #include<iostream>
 using namespace std;
void test01() {
    //第一种方式
     pair<string, int> p("Tom", 20);
cout << "姓名:" << p.first << "年龄:" << p.second << endl;
    //第二种方式
     pair<string, int>p2 = make_pair("Jerry", 30);
     cout << "姓名:" << p2.first << "年龄:" << p2.second << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.9.7set内置数据类型排序
 #include<iostream>
 using namespace std;
 #include<set>
class MyCompare {
 public:
     bool operator()(int v1,int v2) const{
         return v1 > v2;
      }
 };
void test01() {
     set<int>s1;
    s1.insert(10);
     s1.insert(40);
     s1.insert(20);
     s1.insert(30);
     s1.insert(50);
    for (set<int> :: iterator it = s1.begin(); it != s1.end(); it++) {
         cout << *it << " ";
     }
     cout << endl;
    //指定排序规则为从大到小
     set<int,MyCompare>s2;
    s2.insert(10);
     s2.insert(40);
     s2.insert(20);
     s2.insert(30);
     s2.insert(50);
    for (set<int,MyCompare> ::iterator it = s2.begin(); it != s2.end(); it++) {
         cout << *it << " ";
     }
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.9.8set-自定义数据类型排序规则
 //自定义数据类型,set必须指定排序规则才能插入数据
 #include<iostream>
 using namespace std;
 #include<set>
 #include<string>
class Person {
 public:
     Person(string name,int age) {
         this->m_Name = name;
         this->m_Age = age;
     }
    string m_Name;
     int m_Age;
 };
class comparePerson {
 public:
     bool operator()(const Person& p1,const Person& p2) const {
         //按年龄降序
         return p1.m_Age > p2.m_Age;
     }
 };
void test01() {
    //自定义数据类型,都会指定数据类型
     set<Person,comparePerson>s1;
    //创建Person对象
     Person p1("刘备", 30);
     Person p2("关羽", 29);
     Person p3("张飞", 28);
     Person p4("赵云", 28);
     Person p5("马超", 27);
    //插入数据
     s1.insert(p1);
     s1.insert(p2);
     s1.insert(p3);
     s1.insert(p4);
     s1.insert(p5);
    //输出数据
     for (set<Person,comparePerson>::iterator it = s1.begin(); it != s1.end(); it++) {
         cout << "姓名为:" << it->m_Name << "   年龄: " << it->m_Age << endl;
     }
 }
int main(){
test01();
    system("pause");
     return 0;
 }
//25.10map
 //map中所有元素都是pair
 //pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
 //所有元素都会根据元素的键值自动排序
 //本质:map/multimap属于关联式容器,底层结构是用二叉树实现
 //优点:可以根据key值快速找到value值
 //map和multimap区别:map不允许容器中有重复key值元素,multimap允许容器中有重复元素
//24.10.1map构造和赋值
 #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 << "key为:" << (*it).first << "   value = " << it->second << endl;
     }
     cout << endl;
 }
void test01() {
     //创建map容器
     map<int, int> m;
    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>(5, 50));
     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() {
test01();
    system("pause");
     return 0;
 }
//25.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 << "key为: " << (*it).first << " value为: " << (*it).second << endl;
     }
     cout << endl;
 }
//统计大小
 void test01() {
     map<int, int> m;
     m.insert(pair<int, int>(1, 10));
     m.insert(pair<int, int>(2, 20));
     m.insert(pair<int, int>(3, 30));
    //判断是否为空
     if (m.empty()) {
         cout << "m为空" << endl;
     }
     else {
         cout << "m不为空" << endl;
         cout << "m的大小为:" << m.size() << endl;
     }
 }
//交换容器
 void test02() {
     map<int, int> m;
     m.insert(pair<int, int>(1, 10));
     m.insert(pair<int, int>(2, 20));
     m.insert(pair<int, int>(3, 30));
    map<int, int>m2;
     m2.insert(pair<int, int>(4, 40));
     m2.insert(pair<int, int>(5, 50));
     m2.insert(pair<int, int>(6, 60));
    cout << "交换前:  " << endl;
     printMap(m);
     printMap(m2);
    m.swap(m2);
     cout << "交换后:  " << endl;
     printMap(m);
     printMap(m2);
 }
int main() {
        //test01();
     test02();
     system("pause");
     return 0;
 }
//25.10.3map查找和统计
 #include<iostream>
 using namespace std;
 #include<map>
void test01(){
     //查找
     map<int,int>m;
     m.insert(pair<int, int>(1, 10));
     m.insert(pair<int, int>(2, 20));
     m.insert(pair<int, int>(3, 30));
     m.insert(pair<int, int>(3, 40));
map<int, int>::iterator pos = m.find(3);
    if (pos != m.end()) {
         cout << "查到了元素key = " << (*pos).first << ",value = " << pos->second << endl;
     }
     else {
         cout << "未找到元素" << endl;
     }
    //统计
     //map不允许插入重复的key元素,count统计而言,结果要么是0要么是1
     //multimap的count统计可能大于1
     int num = m.count(3);
     cout << "num = " << num << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.10.4map容器排序
 //对于自定义数据类型,map必须要指定排序规则,同set容器
 #include<iostream>
 using namespace std;
 #include<map>
class MyCompare {
 public:
     bool operator()(int v1,int v2) const{
         return v1 > v2;
     }
 };
void test01() {
     map<int, int, MyCompare>m;
     m.insert(make_pair(1, 10));
     m.insert(make_pair(2, 20));
     m.insert(make_pair(3, 30));
     m.insert(make_pair(4, 40));
     m.insert(make_pair(5, 50));
    for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
         cout << "key = " << it->first << " value = " << it->second << endl;
     }
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//25.10.5案例--员工分组
 //案例描述:
 //公司今天招聘了10个员工(ABCDEFGHIJ),需要指派员工在那个部门工作
 //员工信息:姓名 工资组成 ;部门:策划,美术,研发
 //随机给10名员工分配部门和工资
 //通过multimap进行信息的插入 key(部门编号) value(员工)
 //分部门显示员工信息
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<string>
 #include<map>
 #include<ctime>
#define CHEHUA 0
 #define MEISHU 1
 #define YANFA 2
class Worker {
 public:
     string m_Name;
     int m_Salary;
 };
void createWorker(vector<Worker> &v) {
     string nameSeed = "ABCDEFGHIJ";
     for (int i = 0; i < 10; i++) {
         Worker worker;
         worker.m_Name = "员工";
         worker.m_Name += nameSeed[i];
        worker.m_Salary = rand() % 10000 + 10000;//10000~19999
         //将员工放入到容器中
         v.push_back(worker);
    }
 }
//员工分组
 void setGroup(vector<Worker>&v,multimap<int,Worker>&m) {
     for (vector<Worker>::iterator it = v.begin(); it != v.end(); it++) {
         //产生随机部门编号
         int deptId = rand() % 3;//0 1 2
        //将员工插入到分组中
         //key部门编号,value具体员工
         m.insert(make_pair(deptId, *it));
     }
 }
void showWorkerByGroup(multimap<int,Worker> &m) {
     cout << "策划部门:" << endl;
    multimap<int, Worker>::iterator pos = m.find(CHEHUA);
     int count = m.count(CHEHUA);//统计具体人数
     int index = 0;
     for (; pos != m.end() && index < count; pos++, index++) {
         cout << "姓名:" << pos->second.m_Name << "工资:" << pos->second.m_Salary << endl;
     }
    cout << "------------------------------" << endl;
     cout << "美术部门:" << endl;
     pos = m.find(MEISHU);
     count = m.count(MEISHU);//统计具体人数
     index = 0;
     for (; pos != m.end() && index < count; pos++, index++) {
         cout << "姓名:" << pos->second.m_Name << "工资:" << pos->second.m_Salary << endl;
     }
    cout << "------------------------------" << endl;
     cout << "研发部门:" << endl;
     pos = m.find(YANFA);
     count = m.count(YANFA);//统计具体人数
     index = 0;
     for (; pos != m.end() && index < count; pos++, index++) {
         cout << "姓名:" << pos->second.m_Name << "工资:" << pos->second.m_Salary << endl;
     }
}
int main() {
srand((unsigned int)time(NULL));
    //1.创建员工
     vector<Worker>vWorker;
     createWorker(vWorker);
    //2.员工分组
     multimap<int, Worker>mWorker;
     setGroup(vWorker, mWorker);
    //3.分组显示员工
     showWorkerByGroup(mWorker);
    测试
     //for (vector<Worker>::iterator it = vWorker.begin(); it != vWorker.end(); it++) {
     //    cout << "姓名:" << it->m_Name << "  工资:" << it->m_Salary << endl;
     //}
     //cout << endl;
    system("pause");
     return 0;
 }
26.函数对象
 //重载函数调用操作符的类,其对象车策划成为函数对象
 //函数对象使用重载的()时,行为类似函数调用,也叫仿函数
 //本质:函数对象(仿函数)是一个类,不是一个函数
//26.1函数对象使用
 //特点:1.函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
 //2.函数对象超出普通函数的概念,函数对象可以有自己的状态
 //3.函数对象可以作为参数传递
 #include<iostream>
 using namespace std;
 #include<string>
class MyAdd {
 public:
     int operator() (int v1,int v2){
         return v1 + v2;
     }
 };
//1.函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
 void test01() {
     MyAdd myAdd;
     cout << myAdd(10, 10) << endl;
 }
class MyPrint {
 public:
     MyPrint() {
         this->count = 0;
     }
    void operator()(string test) {
         cout << test << endl;
         this->count++;
     }
    int count;//内部自己状态
 };
//2.函数对象超出普通函数的概念,函数对象可以有自己的状态
 void test02() {
     MyPrint myPrint;
     myPrint("hello world");
     myPrint("hello world");
     myPrint("hello world");
     myPrint("hello world");
    cout << "myPrint调用次数:" << myPrint.count << endl;
 }
//3.函数对象可以作为参数传递
void doPrint(MyPrint& mp, string test) {
     mp(test);
 }
void test03() {
     MyPrint myPrint;
     doPrint(myPrint,"Hello");
 }
int main() {
    //test01();
     //test02();
     test03();
    system("pause");
     return 0;
 }
27.谓词
 //返回bool类型的仿函数称为谓词
 //如果operator()接受一个参数,那么叫做一元谓词
 //如果operator()接受两个参数,那么叫做二元谓词
//27.1调用一元谓词
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
class GreaterFive {
 public:
     bool operator()(int val) {
         return val > 5;
     }
 };
void test01() {
     vector<int>v;
     for (int i = 0; i < 10; i++) {
         v.push_back(i);
     }
     //查找容器中,在没有大于5的数字
     //GreaterFive()匿名函数对象
     vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
     if (it == v.end()) {
         cout << "未找到" << endl;
     }
     else {
         cout << "找到了大于5的数字为:" << *it << endl;
     }
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//27.2二元谓词
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
class MyCompare {
 public:
     bool operator()(int val1,int val2){
         return val1 > val2;
     }
 };
void test01() {
     vector<int>v1;
     v1.push_back(10);
     v1.push_back(40);
     v1.push_back(20);
     v1.push_back(30);
     v1.push_back(50);
sort(v1.begin(),v1.end());
    for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
         cout << *it << " ";
     }
     cout << endl;
    //使用函数对象,改变排序规则,变排序规则为从大到小
     sort(v1.begin(), v1.end(), MyCompare());
    cout << "--------------------------" << endl;
     for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
         cout << *it << " ";
     }
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//27.3内建函数对象意义
 //分类:算数仿函数,关系仿函数,逻辑仿函数
 //用法:1.这些仿函数所产生的对象,用法和一般函数完全相同
 //           2.使用内建函数对象,需要引入头文件#include<functional>
//27.3.1算数仿函数
 //功能:实现四则运算,其中negate是一元运算,其他是二元运算
 //仿函数原型:
 //template<class T>  T  plus<T>             //加法仿函数
 //template<class T>  T  minus<T>          //减法仿函数  
 //template<class T>  T  multiplies<T>   //乘法仿函数
 //template<class T>  T  divides<T>        //除法仿函数
 //template<class T>  T  modulus<T>     //取模仿函数
 //template<class T>  T  negate<T>         //取反仿函数
 #include<iostream>
 using namespace std;
 #include<functional>
 void test01(){
    //plus 二元仿函数  加法
     plus<int>p;
     cout << p(10, 20) << endl;
    //minus 二元仿函数 减法
     minus<int>m;
     cout << m(30, 20) << endl;
    //multiplies 二元仿函数 乘法
     multiplies<int>m1;
     cout << m1(4, 6) << endl;
    //divides 二元仿函数 除法
     divides<int>d;
     cout << d(16, 4) << endl;
    //modulus 二元仿函数 取模
     modulus<int>m2;
     cout << m2(100, 10) << endl;
    //negate 一元仿函数 取反仿函数
     negate<int>n;
     cout << n(50) << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//27.3.2关系仿函数
 //仿函数原型:
 //template<class T> bool equal_to<T>            //等于
 //template<class T> bool not_equal_to<T>    //不等于
 //template<class T> bool greater<T>              //大于
 //template<class T> bool greater_equal<T>   //大于等于
 //template<class T> bool less<T>                    //小于
 //template<class T> bool less_equal<T>         //小于等于
 #include<iostream>
 using namespace std;
 #include<functional>
 #include<vector>
 #include<algorithm>
class MyCompare {
 public:
     bool operator()(int var1,int var2) {
         return var1 > var2;
     }
 };
void test01() {
     vector<int>v;
    v.push_back(10);
     v.push_back(30);
     v.push_back(50);
     v.push_back(20);
     v.push_back(40);
    for (vector<int> :: iterator it = v.begin(); it != v.end(); it++) {
         cout << *it << " ";
     }
     cout << endl;
    //降序
     //sort(v.begin(), v.end(),MyCompare());
     //greater<int>()  内建函数对象
     sort(v.begin(), v.end(), greater<int>());
     for (vector<int> ::iterator it = v.begin(); it != v.end(); it++) {
         cout << *it << " ";
     }
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//27.3.3逻辑仿函数
 //template<class T> bool logical_and<T>      //逻辑与
 //template<class T> bool logical_or<T>         //逻辑或
 //template<class T> bool logical_not<T>       //逻辑非
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
 #include<functional>
void test01() {
     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() {
test01();
    system("pause");
     return 0;
 }
28.STL-常用算法
 //算法主要是由头文件<algorithm> <functional> <numeric>组成
 //<algorithm>是所有STL头文件中最大的一个,范围涉及到比较,交换,查找,遍历操作,复刻,修改等等
 //<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数
 //<functional>定义了一些模板类,用以声明函数对象
//28.1常用遍历算法
 //for_each       //遍历容器
 //transform    //搬运容器到另一个容器中
 //28.1.1for_each
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
//普通函数
 void print01(int val) {
     cout << val << " ";
 }
//仿函数
 class print02 {
 public:
     void operator()(int val){
         cout << val << " ";
     }
 };
 void test01() {
     vector<int>v;
     for (int i = 0; i < 10; i++) {
         v.push_back(i);
     }
    for_each(v.begin(), v.end(), print01);
     cout << endl;
    for_each(v.begin(), v.end(), print02());
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.1.2transform
 //功能:搬运容器到另一个容器中
 //函数原型:transform(iterator beg1,iterator end1,iterator beg2,_func);
 //beg1 源容器开始迭代器
 //end1 源容器结束迭代器
 //beg2 目标容器开始迭代器
 //_func 函数或者函数对象
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
class Transform {
 public:
     int operator()(int v) {
         return v+100;
     }
 };
class MyPrint {
 public:
     void operator()(int val) {
         cout << val << " ";
     }
 };
void test01(){
     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(),MyPrint());
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.2常用查找算法
 //find                     //查找元素
 //find_if                 //按条件查元素
 //adjacent_find    //查找相邻重复元素
 //binary_search    //二分查找法
 //count                 //统计元素个数
 //count_if             //按条件统计元素个数
//28.2.1find
 //功能:查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()
 //函数原型:find(iterator beg, iterator end, value);
 //按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
 //beg 开始迭代器
 //end 结束迭代器
 //value 查找的元素
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
 #include<string>
//查找内置数据类型
 void test01() {
     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) {
         this->m_Name = name;
         this->m_Age = age;
     }
    //重载 == 底层find知道如何对比person数据类型
     bool operator==(const Person &p) {
         if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
             return true;
         }
         else {
             return false;
         }
     }
    string m_Name;
     int m_Age;
 };
void test02() {
     vector<Person>v;
     //创建数据
     Person p1("aaa", 10);
     Person p2("bbb", 20);
     Person p3("ccc", 30);
     Person p4("ddd", 40);
    //嵌入到容器中
     v.push_back(p1);
     v.push_back(p2);
     v.push_back(p3);
     v.push_back(p4);
Person pp("bbb", 20);
    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() {
    //test01();
     test02();
    system("pause");
     return 0;
 }
//27.2.2find_if
 //函数原型:find_if(iterator beg, iterator end, _Pred);
 //按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
 //beg 开始迭代器
 //end 结束迭代器
 //_Pred 函数或者谓词(返回bool类型的仿函数)
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
 #include<string>
class GreateFive {
 public:
     bool operator()(int val) {
         return val > 5;
     }
 };
//查找
 void test01(){
     vector<int>v;
     for (int i = 0; i < 10; i++) {
         v.push_back(i);
     }
vector<int>:: iterator it = find_if(v.begin(), v.end(),GreateFive());
    if (it == v.end()) {
         cout << "没有找到" << endl;
     }
     else {
         cout << "找到大于5的数字为:" << *it << endl;
     }
 }
//查找自定义数据类型
 class Person {
 public:
     Person(string name,int age) {
         this->m_Name = name;
         this->m_Age = age;
     }
    string m_Name;
     int m_Age;
 };
class Greater20{
 public:
     bool operator()(Person &p){
         return p.m_Age > 20;
     }
 };
void test02(){
     vector<Person>v;
    //创建数据
     Person p1("aaa", 10);
     Person p2("bbb", 20);
     Person p3("ccc", 30);
     Person p4("ddd", 40);
    v.push_back(p1);
     v.push_back(p2);
     v.push_back(p3);
     v.push_back(p4);
    //找年龄大于20的人
     vector<Person>::iterator it = find_if(v.begin(), v.end(), Greater20());
    if (it == v.end()) {
         cout << "没有找到" << endl;
     }
     else {
         cout << "找到姓名:" << it->m_Name << " 年龄为" << it->m_Age << endl;
     }
 }
int main() {
    //test01();
     test02();
    system("pause");
     return 0;
 }
//28.2.3adjacent_find
 //函数原型:adjacent_find(iterator beg,iterator end);
 //查找相邻重复元素,返回相邻元素的第一个位置的迭代器
 //beg 开始迭代器
 //end 结束迭代器
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
void test01(){
     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 pos = adjacent_find(v.begin(), v.end());
     if (pos == v.end()) {
         cout << "未找到" << endl;
     }
     else {
         cout << "找到相邻重复元素:" << *pos << endl;
     }
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.2.4binary_search
 //函数原型:bool binary_search(iterator beg,iterator end,value);
 //查找指定元素,查到返回true,否则false
 //注意:在无序序列中不可用
 // beg 开始迭代器
 // end 结束迭代器
 // value 查找的元素
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
void test01(){
     vector<int>v;
     for (int i = 0; i < 10; i++) {
         v.push_back(i);
     }
     //v.push_back(2);     如果是无序序列,结果未知!
     //查找容器中是否有9元素
     //注意:容器中是否有序的序列
     bool ret= binary_search(v.begin(), v.end(), 9);
    if (ret) {
         cout << "找到了元素" << endl;
     }
     else {
         cout << "未找到" << endl;
     }
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.2.5count
 //count(iterator beg,iterator end,value);
 //统计元素出现次数
 // beg 开始迭代器
 // end 结束迭代器
 // value 统计的元素
 #include <iostream>
 using namespace std;
 #include <vector>
 #include <algorithm>
void test01() {
     vector<int>v;
    v.push_back(10);
     v.push_back(40);
     v.push_back(30);
     v.push_back(40);
     v.push_back(20);
     v.push_back(40);
    int num = count(v.begin(),v.end(),40);
     cout << "40的元素个数为:" << num << endl;
 }
class Person {
 public:
     Person(string name,int age) {
         this->m_Name = name;
         this->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 test02() {
     vector<Person> v;
    Person p1("刘备", 30);
     Person p2("关羽", 29);
     Person p3("张飞", 28);
     Person p4("赵云", 27);
     Person p5("黄忠", 40);
    v.push_back(p1);
     v.push_back(p2);
     v.push_back(p3);
     v.push_back(p4);
     v.push_back(p5);
Person p("诸葛亮", 30);
int num = count(v.begin(), v.end(), p);
    cout << "跟诸葛亮同岁数的人员个数为:" << num << endl;
 }
int main() {
//test01();
    test02();
     system("pause");
     return 0;
 }
//28.2.6count_if
 //函数原型:count_if(iterator beg,iterator end,_Pred);
 //按照条件统计元素出现次数
 //beg 开始迭代器
 //end 结束迭代器
 //_Pred 谓词
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
class Greater20 {
 public:
    bool operator()(int val){
         return val > 20;
     }
 };
void test01(){
     vector<int>v;
     v.push_back(10);
     v.push_back(40);
     v.push_back(30);
     v.push_back(20);
     v.push_back(40);
     v.push_back(20);
int num = count_if(v.begin(), v.end(), Greater20());
    cout << "大于20的元素个数:" << num << endl;
 }
class Person {
 public:
     Person(string name,int age) {
         this->m_Name = name;
         this->m_Age = age;
     }
    string m_Name;
     int m_Age;
 };
class AgeGreater20 {
 public:
     bool operator()(const Person &p) {
         return p.m_Age > 20;
     }
 };
void test02() {
     vector<Person>v;
    Person p1("刘备", 35);
     Person p2("关羽", 35);
     Person p3("张飞", 35);
     Person p4("黄忠", 40);
     Person p5("马超", 20);
    v.push_back(p1);
     v.push_back(p2);
     v.push_back(p3);
     v.push_back(p4);
     v.push_back(p5);
    //统计大于20的人数
     int num = count_if(v.begin(), v.end(), AgeGreater20());
     cout << "大于20岁的人员个数为:" << num << endl;
 }
int main() {
    //test01();
     test02();
    system("pause");
     return 0;
 }
//28.3常用排序算法
 //sort                         //对容器内元素进行排序
 //random_shuffle     //洗牌  指定范围内的元素随机调整次序
 //merge                     //容器元素合并,并存储到另一容器
 //reverse                    //反转指定范围的元素
28.3.1sort
 //函数原型:sort(iterator beg,iterator end,_Pred);
 //按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
 //beg 开始迭代器
 #include <iostream>
 using namespace std;
 #include <algorithm>
 #include <vector>
 #include <functional>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     vector<int>v;
    v.push_back(10);
     v.push_back(30);
     v.push_back(50);
     v.push_back(20);
     v.push_back(40);
    //利用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() {
test01();
    system("pause");
     return 0;
 }                
//28.3.2random_shuffle
 //random_shuffle(iterator beg,iterator end);
 //指定范围内的元素随机调整次序
 //beg 开始迭代器
 //end 结束迭代器
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
 #include<ctime>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     //random_shuffle洗牌算法比较实用,使用时记得加随机数种子
     srand((unsigned int)time(NULL));
    vector<int>v;
     for (int i = 0; i < 10; i++) {
         v.push_back(i);
     }
    //利用洗牌算法打乱顺序
     random_shuffle(v.begin(),v.end());
    for_each(v.begin(), v.end(), myPrint);
     cout << endl;
}
int main() {
test01();
    system("pause");
     return 0;
 }
//28.3.3merge
 //功能:两个容器元素合并,并存储到另一容器中
 //函数原型:merge(iterator beg1,iterator beg2,iterator end2,iterator dest);
 //容器元素合并,并存储到另一容器中
 //注意:两个容器必须是有序的
 //beg1  容器1开始迭代器
 //end1 容器1结束迭代器
 //beg2 容器2开始迭代器
 //end2 容器2结束迭代器
 //dest 目标容器开始迭代器
 #include <iostream>
 using namespace std;
 #include <vector>
 #include <algorithm>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     vector<int>v1;
     vector<int>v2;
    for (int i = 0; i < 10; i++) {
         v1.push_back(i);
         v2.push_back(i + 1);
     }
    //目标容器
     vector<int>vTarget;
    //提前给目标容器分配空间
     vTarget.resize(v1.size() + v2.size());
     //合并需要两个有序序列
     merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
    for_each(vTarget.begin(), vTarget.end(), myPrint);
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.3.4reverse
 //功能:将容器内元素进行反转
 //函数原型:reverse(iterator beg,iterator end);
 //反转指定范围的元素
 //beg 开始迭代器
 //end 结束迭代器
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     vector<int>v;
     v.push_back(10);
     v.push_back(30);
     v.push_back(50);
     v.push_back(20);
     v.push_back(40);
     
     cout << "反转前:" << endl;
     for_each(v.begin(),v.end(),myPrint);
     cout << endl;
    cout << "反转后:" << endl;
     reverse(v.begin(), v.end());
     for_each(v.begin(), v.end(), myPrint);
     cout << endl;
}
int main() {
test01();
    system("pause");
     return 0;
 }
//28.4常用拷贝和替换算法
 //copy:          //容器内指定范围的元素拷贝到另一容器中
 //replace         //将容器内指定范围的旧元素改为新元素
 //replace_if     //容器内指定范围满足条件的元素替换为新元素
 //swap            //互换两个容器的元素
//28.4.1copy
 //copy(iterator beg,iterator end,iterator dest);
 //按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
 //beg 开始迭代器
 //end 结束迭代器
 // dest 目标起始迭代器
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     vector<int>v;
     for (int i = 0; i < 10; i++) {
         v.push_back(i);
     }
    vector<int>v2;
     v2.resize(v.size());
     copy(v.begin(), v.end(), v2.begin());
    for_each(v2.begin(),v2.end(),myPrint);
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.4.2replace
 //函数原型:replace(iterator beg,iterator end,oldvalue,newvalue);
 //将区间内旧元素替换为新元素
 //beg 开始迭代器
 //end 结束迭代器
 //oldvalue  旧元素
 //newvalue 新元素
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
class MyPrint {
 public:
     void operator()(int val) {
         cout << val << " ";
     }
 };
void test01() {
     vector<int>v;
    v.push_back(20);
     v.push_back(30);
     v.push_back(50);
     v.push_back(30); 
     v.push_back(40);
     v.push_back(20);
     v.push_back(10);
     v.push_back(20);
    cout << "替换前:" << endl;
     for_each(v.begin(), v.end(), MyPrint());
     cout << endl;
    //将20替换为200
     replace(v.begin(), v.end(), 20, 200);
     cout << "替换:" << endl;
     for_each(v.begin(),v.end(),MyPrint());
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.4.3replace_if
 //函数原型:replace_if(iterator beg,iterator end,_pred,newvalue);
 //按条件替换元素,满足条件的替换成指定元素
 //beg 开始迭代器
 //end 结束迭代器
 //_pred 谓词
 //newvalue 替换的新元素
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
class MyPrint {
 public:
     void operator()(int val) {
         cout << val << " ";
     }
 };
class Greater30 {
 public:
     bool operator()(int val) {
         return val > 30;
     }
 };
void test01() {
     vector<int>v;
     v.push_back(10);
     v.push_back(40);
     v.push_back(20);
     v.push_back(40);
     v.push_back(30);
     v.push_back(50);
     v.push_back(20);
     v.push_back(30);
    cout << "替换前:" << endl;
     for_each(v.begin(), v.end(), MyPrint());
     cout << endl;
    //将大于等于30  替换为3000
     replace_if(v.begin(), v.end(), Greater30(),3000);
     cout << "替换后:" << endl;
     for_each(v.begin(), v.end(), MyPrint());
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.4.4swap
 //函数原型:swap(container c1,container c2);
 //互换两个容器的元素
 //c1容器1
 //c2容器2
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     vector<int>v1;
     vector<int>v2;
    for (int i = 0; i < 10; i++) {
         v1.push_back(i);
         v2.push_back(i+100);
     }
    cout << "交换前:" << endl;
     for_each(v1.begin(),v1.end(),myPrint);
     cout << endl;
     for_each(v2.begin(),v2.end(),myPrint);
     cout << endl;
    cout << "----------------------------------" << endl;
     cout << "交换后:" << endl;
swap(v1,v2);
    for_each(v1.begin(), v1.end(), myPrint);
     cout << endl;
     for_each(v2.begin(), v2.end(), myPrint);
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.5常用算术生成算法
 //注意:算术生成算法属于小型算法,使用时包含的头文件为#include <numeric>
 //accumulate            //计算容器元素累计总和
 //fill                           //向容器中添加元素
//28.5.1accumulate
 //函数原型:accumulate(iterator beg,iterator end,value);
 //beg 开始迭代器
 //end 结束迭代器
 //value 起始值
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<numeric>
void test01() {
     vector<int>v;
    for (int i = 0; i < 100; i++) {
         v.push_back(i);
     }
     //参数3 起始累加值
     int total = accumulate(v.begin(),v.end(),1000);
    cout << "total = " << total << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.5.2fill
 //fill(iterator beg,iterator end,value);
 //向容器中填充元素
 //beg 开始迭代器
 //end 结束迭代器
 //value 填充的值
 #include<iostream>
 using namespace std;
 #include<numeric>
 #include<vector>
 #include<algorithm>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     vector<int>v;
     v.resize(10);
    //后期重新填充
     fill(v.begin(), v.end(), 100);
    for_each(v.begin(),v.end(),myPrint);
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }
//28.6常用集合算法
 //set_intersection       //求两个容器的交集
 //set_union                  //求两个容器的并集
 //set_difference           //求两个容器的差集
//28.6.1set_intersection
 //函数原型:set_intersection(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
 //求两个集合的交集
 //注意:两个集合必须是有序序列
 //beg1 容器1开始迭代器
 //end1 容器1结束迭代器
 //beg2 容器2开始迭代器
 //end2 容器2结束迭代器
 //dest 目标容器开始迭代器
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     vector<int>v1;
     vector<int>v2;
     for (int i = 0; i < 10; i++) {
         v1.push_back(i);        //0~10
         v2.push_back(i+5);      //5~14
     }
    vector<int>vTarget;
     //目标容器需要提前开辟空间
     //最特殊情况 大容器包含小容器 开辟空间 取最小容器的size即可
     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() {
test01();
    system("pause");
     return 0;
 }
//28.6.2set_union
 //函数原型:set_union(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
 //注意:两个集合必须是有序序列
 //beg1 容器1开始迭代器
 //end1 容器1结束迭代器
 //beg2 容器2开始迭代器
 //end2 容器2结束迭代器
 //dest 目标容器开始迭代器
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     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;
     //目标容器提前开辟空间
     //最特殊情况,两个容器没有交集,并集就是两个容器size相加
     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() {
test01();
    system("pause");
     return 0;
 }
//28.6.3set_difference
 //函数原型:set_difference(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
 //注意:两个集合必须是有序序列
 //beg1 容器1开始迭代器
 //end1 容器1结束迭代器
 //beg2 容器2开始迭代器
 //end2 容器2结束迭代器
 //dest 目标容器开始迭代器
 #include<iostream>
 using namespace std;
 #include<vector>
 #include<algorithm>
void myPrint(int val) {
     cout << val << " ";
 }
void test01() {
     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;
     //给目标容器开辟空间
     //最特殊情况 两个容器没有交集 取两个容器中大的sie()作为目标容器开辟空间
     vTarget.resize(max(v1.size(),v2.size()));
cout << "v1和v2的差集为:" << endl;
vector<int>::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
    for_each(vTarget.begin(), itEnd, myPrint);
     cout << endl;
cout << "v2和v1的差集为:" << endl;
itEnd = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), vTarget.begin());
    for_each(vTarget.begin(), itEnd, myPrint);
     cout << endl;
 }
int main() {
test01();
    system("pause");
     return 0;
 }