[4] C++高级编程

Day1

常量补充

//--Day1.cpp
#pragma region 常量补充
    // 常对象和常函数
    const Student S1{ 10010, "张三", 1500 };
    S1.GetID();
     S1.SetID(10015); //调用非常函数会报错
#pragma endregion

//-- Student.h
#pragma once
#include <iostream>

class Student
{
protected:
	int ID;
	std::string Name;
	
	// 类中有const成员变量,初始化只能使用初始化列表
	// 构造函数中必须给常量成员做初始化,否则会报错
	const int Num;

public:
	static int Count;
	
	Student();
	Student(int ID, std::string Name, int Num);

	inline int GetID() const { return ID; }
	inline void SetID(int ID) { this->ID = ID; }

	inline std::string GetName() const { return Name; }
	inline void SetName(std::string Name) { this->Name = Name; }
};

// int Student::Count = 0;  // 语法错误

静态成员函数和静态成员

Day.cpp
 #pragma region 静态成员函数和静态成员
    // 静态 static

    // 静态成员在使用之前必须初始化(静态成员初始化有自己独特的方式)
    // 静态成员变量可以直接通过类访问(::),不用必须创建对象
    // 静态成员变量既可以通过类访问,也可以通过对象访问(. ->)
    // 本质 静态成员变量  是所有对象共享的
    Student::Count = 100;

    Student S1;
    cout << S1.Count << endl;

    Student S2;
    cout << S2.Count << endl;

    Student::Count = 500;
    cout << S1.Count << endl;
    cout << S2.Count << endl;

    S1.Count = 1000;
    cout << S1.Count << endl;
    cout << S2.Count << endl;

    cout << &S1.Count << endl;
    cout << &S2.Count << endl;
    cout << &Student::Count << endl;

    // 作用  同一个类不同对象共享 
    // 提供一种方式,可以统计当前类有多少个对象(构造++,析构--)
    // Set   Get  
    cout << Student::GetCount() << endl;
    {
        Student* S1 = new Student();
        Student S2;
        cout << Student::GetCount() << endl;
    }
    cout << Student::GetCount() << endl;

    // 静态成员函数
    // 在普通成员函数前加static
    // 静态成员函数中不允许访问非静态的成员变量和成员函数
    // 在普通成员函数中可以访问静态成员变量和静态成员函数
   
    // 继承中的静态
    // 父类对象和子类对象的静态成员变量地址是一致的
    Student S1;
    Pupil P1;

    cout << &S1.Count << endl;
    cout << &P1.Count << endl;

    cout << "End" << endl;

#pragma endregion
Student.h.cpp
 #pragma once
#include <iostream>

class Student
{
protected:
	int ID;
	std::string Name;
	
	// 类中有const成员变量,初始化只能使用初始化列表
	// 构造函数中必须给常量成员做初始化,否则会报错
	const int Num;

	

public:
	static int Count;
	

	Student();
	Student(int ID, std::string Name, int Num);

	inline int GetID() const { return ID; }
	inline void SetID(int ID) { this->ID = ID; }

	inline std::string GetName() const { return Name; }
	inline void SetName(std::string Name) { this->Name = Name; }

	inline static int GetCount() { 
		return Count;
	}

	void Test() const;

	int GetNum() const;

	virtual ~Student();
};

// int Student::Count = 0;  // 语法错误

//-- cpp
#include "Student.h"


int Student::Count = 0; // 推荐使用这种方式

Student::Student()
	: ID(0), Name(""), Num(0)
{
	Count++;
}

Student::Student(int ID, std::string Name, int Num)
	: Num(Num)
{
	this->ID = ID;
	this->Name = Name;
	Count++;
}

void Student::Test() const
{
	// ID = 10012; // 当前对象的属性不能修改
	GetID(); // 在一个常函数中可以调用另外一个常函数
	// SetID(10015); // 在一个常函数内部不允许调用非常函数

	


	// 创建一个临时对象(可以调用临时对象的非常量成员)
	// 如果创建的是const临时对象,依然需要遵循上面的规则
	Student S1;
	S1.ID = 10015;

}

int Student::GetNum() const
{
	return Num;
}

Student::~Student()
{
	Count--;
}

设计模式-单例模式

C++各类设计模式及实现详解

Day.cpp
 #pragma region 单例模式
    // 设计模式

    // 设计模式使简单的问题复杂化,使复杂的问题简单化

    // 单例模式  整个程序的声明周期内,某一个类有且只有同一个对象
    // 1、把构造函数变成private  ->  防止在类的外部进行new对象
    // 2、创建一个private的静态成员,用来存储唯一的对象
    // 3、定义一个public的静态函数,用来访问提供的唯一的对象
    
    {
        cout << GameInstance::GetInstance()->GetID() << endl;
        GameInstance::GetInstance()->SetID(10050);
        cout << GameInstance::GetInstance()->GetID() << endl;
    }
     Test();
    // 添加其他成员
    
    // 
    // delete销毁  (static变量是游戏开始就存在,直到游戏结束才会被销毁)
    // 表现上 单例类的析构貌似没有调用

    // 练习 
    // 一个公司只有一台打印机,员工A打印加薪申请,员工B打印简历,打印机需要记录打印了哪些份文件
    auto Printer = PrinterManager::GetManager();
    Printer->Print("加薪申请");
    Printer->Print("简历");
    Printer->Print("加班申请");
    Printer->ShowHistory();
    Printer->ClearHistory();
    Printer->ShowHistory();

    
#pragma endregion
GameInstance.h.cpp
 #pragma once
#include <iostream>

    // 1、把构造函数变成private  ->  防止在类的外部进行new对象
    // 2、创建一个private的静态成员,用来存储唯一的对象
    // 3、定义一个public的静态函数,用来访问提供的唯一的对象

class GameInstance
{
private:
    GameInstance();

    // 推荐使用指针
    static GameInstance* Instance; 

    int ID;

public:
    inline int GetID() const { return ID; }
    inline void SetID(int ID) { this->ID = ID; }

    virtual ~GameInstance()
    {
        if (Instance)
        {
            delete Instance;
            Instance = nullptr;
            std::cout << "调用析构" << std::endl;
        }
    }

    // static和const无法连用
    static GameInstance* GetInstance() 
    {
        if (!Instance) // 如果Instance是一个空指针,需要new一个对象
        {
            Instance = new GameInstance();
        }
        return Instance;
    }
};
//--cpp
#pragma once
#include <iostream>

    // 1、把构造函数变成private  ->  防止在类的外部进行new对象
    // 2、创建一个private的静态成员,用来存储唯一的对象
    // 3、定义一个public的静态函数,用来访问提供的唯一的对象

class GameInstance
{
private:
    GameInstance();

    // 推荐使用指针
    static GameInstance* Instance; 

    int ID;

public:
    inline int GetID() const { return ID; }
    inline void SetID(int ID) { this->ID = ID; }

    virtual ~GameInstance()
    {
        if (Instance)
        {
            delete Instance;
            Instance = nullptr;
            std::cout << "调用析构" << std::endl;
        }
    }

    // static和const无法连用
    static GameInstance* GetInstance() 
    {
        if (!Instance) // 如果Instance是一个空指针,需要new一个对象
        {
            Instance = new GameInstance();
        }
        return Instance;
    }
};

运算符重载

A + B //- 运算符重载
A - B //+ 运算符重载
A > B //> 运算符重载
A > B // > 运算符重载
A++ // 后置++ 运算符重载
++A // 前置++ 运算符重载
A = B // = 号运算符重载
A == B // ==运算符重载
cout << // <<输出运算符重载
cin >> //输入运算符重载

Day.cpp
#pragma region 运算符重载
	int Num = 10;
	Complex C1(2, 5, Num);
	Complex C2(2, 5, Num);
	Complex C3 = C1 + C2; // +

	Complex C4 = C2 - C1;// - 

	C3.Display();
	C4.Display();

	cout << (C1 > C2) << endl; // > 

	cout << (C1 == C2) << endl; // == 
	
	(++C1).Display();// 前置++

	C1++; //后置++
	C1.Display();

	cout << C1; // <<

	cin >> C1; // >>
	cout << C1;
	Complex C3 = Complex (2, 5, Num);// =
	C2 = C1;


	system("Pause");

#pragma endregion
Complex
//-- .h
#pragma once
#include <iostream>

class Complex
{
	friend Complex operator+(const Complex& A, const Complex& B); //有元

	friend Complex operator-(const Complex& A, const Complex& B);

	friend bool operator>(const Complex& A, const Complex& B);

	friend std::ostream& operator<<(std::ostream& Out, const Complex& C);

	friend std::istream& operator>>(std::istream& stream, Complex& C);

protected:
	int Real;
	int Imagine;
	int* Ptr = nullptr;
public:
	Complex();
	Complex(int Real, int Imagine,int Num);
	Complex operator+ (const Complex & Another); //成员函数比全局有员优先级高
	Complex& operator++(); //后置++
	Complex operator++(int); //前置++
	Complex operator=(const Complex& Another); // = 

	bool operator==(const Complex& Another); // ==

	void Display();
};


//-- .cpp
#include "Complex.h"
#include <iostream>

using namespace std;

Complex::Complex()
	:Real(1),Imagine(1)
{
}

Complex::Complex(int Real, int Imagine)
	:Real(Real),Imagine(Imagine)
{
}

Complex Complex::operator+(const Complex& Another)
{
	return Complex(this->Real + Another.Real,this->Imagine + Another.Imagine);
}


void Complex::Display()
{
	cout << Real << "+" << Imagine << "i" << endl;
}

Day2

STL简介

Day.cpp
 #pragma region STL简介
	// Standard Template Library  标准泛型库
	// 容器  算法  仿函数【匿名函数】  迭代器  (适配器  分配器)
#pragma endregion

vector

Day.cpp
 #pragma region vector
   // // 动态数组(可变数组) 删除、插入
   // // 基本语法 vector<类型>
   // // vector是可变数组,所以没有必要一开始给一个长度

	vector<int> Nums;
	cout << Nums.empty() << endl;
	// // size() 数组的真正的大小    capacity() 可变容量
	// // 插入元素push_back()
	for (int i = 0; i < 10; ++i)
	{
		Nums.push_back(i); // 尾插
		cout << Nums.size() << " " << Nums.capacity() << endl;
	}

	for (int i = 0; i < Nums.size(); ++i)
	{
		// 访问数组的元素
		cout << Nums[i] << endl;
		cout << Nums.at(i) << endl;
	}

	  cout << Nums.at(10) << endl; // vector也存在越界的问题(崩溃)
	 cout << Nums.front() << endl; // 返回第0个元素的值
	 cout << Nums.back() << endl; // 返回最后一个元素

	// // empty() 判断数组是否为空  如果为空返回true,否则返回false
	 cout << Nums.empty() << endl;
	 Nums.resize(20, 100); // 重置数组的长度 既可以单独制定长度(用默认值填充),也可以同时制定要填充的值
	 cout << Nums.size() << endl;

	// cout << "=============" << endl;
	//// // 迭代器 begin()指向第0个元素的地址,end()指向最后一个元素后面的地址(不属于数组)
	//// // for(auto It = ::begin; It != ::end(); ++It)
	 for (auto It = Nums.begin(); It != Nums.end(); ++It)
	 {
	     // It是一个迭代器,*解引用 *It 
	     cout << *It << endl;
	 }
	 cout << "=============" << endl;
	 cout << "删除前的大小" << Nums.size() << endl;
	 Nums.pop_back(); // 把尾部的元素进行删除  跟push_back对应
	 cout << "删除后的大小" << Nums.size() << endl;

	////// 插入(位置,元素)
	 Nums.insert(Nums.begin(), 50); // 在某一个迭代器(位置)之前插入一个元素,值为50
	 Nums.insert(Nums.end(), 5, 500); // 在数组的结尾的位置插入5个500
	//// 

	//// // 移除
	 Nums.erase(Nums.begin()); // 代表移除迭代器对应位置的元素
	 Nums.erase(Nums.begin(), Nums.begin() + 5);
	 cout << "End" << endl;

	//// // 清空
	 Nums.clear(); // 影响的是size(),capacity()不一定受影响

	//// //// reserve  预留 保留
	 vector<string> Names;

	 Names.reserve(10); // 相当于设置了容量  // resize会填充默认值,reserve不会
	  cout << Names[0] << endl;

	//// //// swap 数组的交换    两个数组的类型必须一致
	 vector<int> Nums1;
	 Nums1.push_back(1);
	 Nums1.push_back(2);

	 vector<int> Nums2;
	 Nums2.insert(Nums2.begin(), 10, 500);

	  Nums1 = Nums2; // 将Nums2的值给到Nums1,Nums2不受影响
	 Nums1.swap(Nums2); // 交换两个数组的值
	 cout << "" << endl;

	//// // 移除元素的注意点
	vector<int> Nums1;
	for (int i = 0; i < 10; ++i)
	{
		Nums1.push_back(i);
	}
	// 如果使用It对数组进行访问,数组进行长度变化之后原来的It失效,刷新It的值
	vector<int>::iterator It = Nums1.begin();
	Nums1.insert(Nums1.begin(), 20);
	It = Nums1.begin();
	//cout << *It << endl;

	Nums1.insert(Nums1.begin() + 3, 50);
	// // 把Nums1中第一个出现的50进行移除


	//Nums1.insert(Nums1.begin() + 2, 5, 50);
	// // 把Nums1所有的50的元素删除
	for (auto IT = Nums1.begin(); IT != Nums1.end();)
	{

		if (*IT == 50) {
			cout << &IT << endl; //000000138D2FF2E8
			cout << *IT << endl; // 删除前50

			IT = Nums1.erase(IT); //返回了下一个迭代器的位置
			cout << &IT << endl; // 元素还是那个元素只不过往前移了
			cout << *IT << endl; //000000138D2FF2E8 地址

			cout << &(*IT) << endl;
		}
		else {
			++IT;
		}
	}

#pragma endregion

vector高级

Day.cpp
 #pragma region vector高级
	//// 1、vector文件读写
	vector<string> Names;
	Names.push_back("陈平安");
	Names.push_back("秀秀");
	Names.push_back("老秀才");

	ofstream Out;
	Out.open("Names.txt");
	for (auto It = Names.begin(); It != Names.end(); ++It)
	{
	    Out << *It << endl;
	}
	Out.close();

	//// 读文件
	ifstream In;
	In.open("Names.txt");
	string Name;
	vector<string> Names1;
	while (getline(In, Name))
	{
	    Names1.push_back(Name);
	}
	In.close();
	cout << "End" << endl;

	//vector<MyStruct>;


	// 2、vector嵌套
	vector<vector<int>> Nums1;

	vector<int> Nums2;
	Nums2.push_back(5);

	vector<int> Nums3;
	Nums3.push_back(1);
	Nums3.push_back(2);

	vector<int> Nums4;
	Nums4.push_back(100);
	Nums4.push_back(200);
	Nums4.push_back(300);
	Nums4.push_back(400);

	Nums1.push_back(Nums2);
	Nums1.push_back(Nums3);
	Nums1.push_back(Nums4);

	//普通for遍历
	for (int i = 0; i < Nums1.size(); ++i)
	{
		for (int j = 0; j < Nums1[i].size(); ++j)
		{
			cout << Nums1[i][j] << " ";
		}
		cout << endl;
	}

	//迭代器遍历
	for (auto IT1 = Nums1.begin(); IT1 < Nums1.end(); IT1++)
	{
		for (auto IT2 = (*IT1).begin(); IT2 != (*IT1).end(); IT2++)
		{
			cout << *IT2 << " ";
		}
		cout << endl;
	}

#pragma endregion

Day3

按钮事件分发器

按钮事件分发器
#pragma region 按钮事件分发器
void SayHi() {
	cout << "SayHi" << endl;
}
void SayBey() {
	cout << "SayBey" << endl;
}
void SayHeeloWorld() {
	cout << "SayHeeloWorld" << endl;
}

AButton B1;
B1.BindEventToOnClicked(SayHi)
		.BindEventToOnClicked(SayBey)
		.BindEventToOnClicked(SayHeeloWorld); //链式调用
B1.BindEventToOnClicked(SayBey);
B1.BindEventToOnClicked(SayHeeloWorld);

B1.UnbindEvent(SayBey);
B1.Click();

#pragma endregion

//--Button.h.cpp
#pragma once
#include <vector>
#include <string>
#include <iostream>

using namespace std;

//定义无参无返回值
typedef void (*Ptr)();

class AButton
{
protected:
	vector<Ptr> Onclicked;
public:
	AButton& BindEventToOnClicked(Ptr Event);
	void UnbindEvent(Ptr Event);
	void UnbindAll();
	void Click();

};

AButton& AButton::BindEventToOnClicked(Ptr Event)
{
	auto IT = find(Onclicked.begin(), Onclicked.end(), Event);
	if (IT == Onclicked.end()) Onclicked.push_back(Event);
	return *this;
}

void AButton::UnbindEvent(Ptr Event)
{
	auto IT = find(Onclicked.begin(), Onclicked.end(), Event);
	if (IT != Onclicked.end()) Onclicked.erase(IT);
}

void AButton::UnbindAll()
{
	Onclicked.clear();
}

void AButton::Click()
{
	for (auto IT = Onclicked.begin(); IT != Onclicked.end(); IT++)
	{
		(*IT)();
	}
}

list链表

Day.cpp
 #pragma region list链表
   list<int> Nums;

   // 尾部添加元素
   Nums.push_back(10);
   Nums.push_back(20);
   // 链表中无法通过索引访问元素
    cout << Nums[1] << endl;

   for (auto It = Nums.begin(); It != Nums.end(); ++It)
   {
       cout << *It << " " << &*It << endl;
   }
   cout << endl;
   // 反转链表
   Nums.reverse();
   //

   // //// list的迭代器没有办法进行 +  -   支持++ -- 
   Nums.insert(--Nums.end(), 50);

   Nums.erase(Nums.begin());
   
   //cout << Nums.front() << " " << Nums.back() << endl;
   //cout << Nums.max_size(); // 最大容量

   // list为什么没有capacity() 容量
   Nums.push_front(100);
   Nums.push_front(100);
   Nums.push_front(100);
   Nums.push_front(100);
   
   Nums.remove(100); // 移除所有制定的元素
   for (auto It = Nums.begin(); It != Nums.end(); ++It)
   {
       cout << *It << " " << &*It << endl;
   }


    vector<int> Nums;
    srand(time(0));
    for (int i = 0; i < 10; ++i)
    {
        Nums.push_back(rand());
    }
   // //// 包含algorithm头文件
   sort(Nums.begin(), Nums.end());
   cout << "Enmd" << endl;

   // sort排序如果类型自带了排序优先使用自带的排序
   list<int> Nums1;
   srand(time(0));
   for (int i = 0; i < 10; ++i)
   {
   Nums1.push_back(rand());
   }
   Nums1.sort();
   cout << "Enmd" << endl;

   // // (动态)数组与链表list的主要不同
   // // 1、数组访问元素速度非常快,增加和删除元素比较慢
   // // 2、list访问元素的速度非常慢,增加和删除元素的速度比较快

   // // 链表
   // // 单向链表  双向链表  循环链表
    
#pragma endregion

map字典

Day.cpp
 #pragma region map字典
    //// 键值对   由一个键和一个值组成的一组数据叫做键值对
    pair<int, string> P1(10010, "张三");
    pair<int, string> P2{ 10011, "里斯" };
    pair<int, string> P3 = make_pair(10012, "王五");

   


    vector<int> Nums;
    Nums.push_back(100);
    Nums.push_back(500);
    pair<string, vector<int>> P4 = { "北京", Nums};

    pair<string, vector<vector<string>>> P5;

    //// map 字典映射  有一组一组的键值对组成
    map<int, string> Error;
    //// 字典的插入或者赋值
    Error.insert(make_pair(10010, "赵六"));
    Error[10015] = "欧阳娜娜";
    Error.insert(pair<int, string>(10011, "初七"));
    Error.insert(map<int, string>::value_type(10012, "刘八"));
    //

    //

    //// 字典类型插入顺序和存储顺序无关,字典内部对于key有一套自己的排序规则,插入的时候会自动排序
    cout << endl;
    cout << Error.at(10015) << endl;
    Error[10015] = "李白";
    cout << Error[10015] << endl;

    //// 迭代器
    //// 字典遍历
    for (auto It = Error.begin(); It != Error.end(); ++It)
    {
        // *It返回的是pair   通过first和second访问key 和 value
        cout << "Key:" << (*It).first << ", Value: " << (*It).second << endl;
    }

    cout << endl;
    //// rbegin表示容器最后一个元素,rend表示容器第0个元素左侧的内存
    //// begin表示容器第0个元素的地址,end表示容器最后一个元素后面的空间
    //// c开头表示常量迭代器,只能访问不能修改


    //// 字典作为参数的时候,默认使用值传递,可以使用引用和指针内外同时修改
    TestMap(Error);
    for (auto It = Error.rbegin(); It != Error.rend(); ++It)
    {
        cout << "Key:" << (*It).first << ", Value: " << (*It).second << endl;
    }

    //// 清除字典
     Error.clear();

    ////// 删除元素1根据key
    Error.erase(10015);
    // 字典的迭代器不支持 + - 但是支持++ --
    Error.erase(Error.begin(), ++++Error.begin()); // 相当于删除前两个元素

    cout << Error.count(10015) << endl; // 查找字典中有没有指定的key

    //// find返回值是迭代器,如果没有找到会返回对应的end()
    auto Result = Error.find(10015); // 根据key的值去查找,返回值是一个迭代器,*解引用之后就是一个pair
    if (Result == Error.end())
    {
        cout << "没有找到" << endl;
    }
     
    
    cout << "End" << endl;
#pragma endregion

字典高级

Day.cpp
 struct AStudent
{
	int ID = 0;
	string Name = "";
	AStudent();
	AStudent(int ID, string Name);
	bool operator>(const AStudent& Another)const {
		return this->ID > Another.ID;
	}
	bool operator<(const AStudent& Another)const {
		return this->ID < Another.ID;
	}
};
struct StudentCompare //Asutdnet的仿函数
{
	bool operator()(const AStudent& S1, const AStudent& S2)const {
		return S1.ID > S2.ID;
		//return true;

	}
};

//防函数 结构体形式
struct IntCompare
{
	bool operator()(const int& Key1, const int& Key2)const {
		return Key1 > Key2;
	}
};

//类形式
class IntCompare1
{
public:
	bool operator()(const int& Key1, const int& Key2)const {
		return Key1 > Key2;
	}
};
#pragma region 字典高级


	//--防函数

	map<int, string, IntCompare1>Error; // 自定义仿函数
	map<int, string, greater<IntCompare1>>Error; // 自定义仿函数 倒序
	pair<int, string> P1(1, "11");

	//map<int, string>Error;

	Error[10010] = "22";
	Error[10012] = "11";
	Error.insert(P1);
	Error.insert(map<int, string>::value_type(7, "77"));
	Error[10015] = "55";
	Error.insert(pair<int, string>(6, "66"));
	Error.insert(make_pair(4, "44"));
	Error[102] = "33";

	for (auto IT = Error.begin(); IT != Error.end(); IT++)
	{
		cout << (*IT).first << " : " << (*IT).second << endl;
	}

	//IntCompare IC; //防函数
	//cout << IC(80, 70) << endl;

	// 自定义类型作为key
	// 单纯定义变量不会报错,一旦插入的时候就会报错
	// 仿函数定义的是排序规则,不能使用 == !=    必须是 > < >= <= 否则字典只能保存一个元素
	//// 系统自带的仿函数
	//less<int> Less;
	//cout << Less(50, 80) << endl

	//-- 结构体仿函数
	map < AStudent, int, greater<AStudent>> AstudentMap; //自定义了 仿函数
	//map < AStudent, int, greater<AStudent>> AstudentMap; //自定义了 仿函数

	pair< AStudent, int> S1(AStudent(11, "22"), 222);
	pair< AStudent, int> S2(AStudent(22, "33"), 333);

	AstudentMap.insert(S1);
	AstudentMap.insert(S2);

	AstudentMap.insert(pair< AStudent, int>(AStudent(44, "55"), 555));

	for (auto IT = AstudentMap.begin(); IT != AstudentMap.end(); IT++)
	{
		cout << (*IT).first.ID << " : " << (*IT).first.ID << "  value" << (*IT).second << endl;
	}


#pragma endregion

Day4

Set

Day.cpp
struct MyStruct
{
    int ID;
    string Name;
};
#pragma region set
    //// 高一 集合   字典的简化, 集合中存储的是只有键没有值的字典
    //// 内部元素不允许重复
    set<int> Nums;
    Nums.insert(10);
    Nums.insert(20);
    Nums.insert(10); // 重复元素插入失败
    cout << Nums.size() << endl;

    //// 集合的遍历
    for (auto It = Nums.begin(); It != Nums.end(); ++It)
    {
        cout << *It << endl;
    }
    // 集合常用的算法
    // count可以用来检查集合中是否包含某一个指定的元素
    cout << Nums.count(15) << endl;
    // find
    cout << endl;
    auto It = Nums.find(20);
    if (It != Nums.end())
    {
        // *It = 200; // 集合元素默认是不循序改的
        cout << *It << endl;
    }


    set<int> Nums1;
    Nums1.insert(100);
    Nums1.insert(200);

    set<int> Nums2;
    Nums2.insert(5);
    Nums2.insert(200);
    Nums2.insert(10);

    set<int> Results;
    // 集合中的运算   
    // 需要先导入算法头文件 algorithmn
    // 并集
    set_union(Nums1.begin(), Nums1.end(), Nums2.begin(), Nums2.end(), inserter(Results, Results.begin()));
    // 差集 不支持交换律
     set_difference(Nums2.begin(), Nums2.end(), Nums1.begin(), Nums1.end(), inserter(Results, Results.begin()));
    // 交集
     set_intersection(Nums1.begin(), Nums1.end(), Nums2.begin(), Nums2.end(), inserter(Results, Results.begin()));
    for (auto It = Results.begin(); It != Results.end(); ++It)
    {
        cout << &*It << endl;
    }

    set<MyStruct> Strucs;
    Strucs.insert({ 10010, "张三" });
#pragma endregion

Queue

Day.cpp
 #pragma region queue
    //// 队列  队   先进先出(排队)
    //// 默认不支持插队
    queue<int> Nums;
    Nums.push(50);
    Nums.push(20);
    Nums.push(50);
    cout << Nums.size() << endl;
    // 不支持迭代器(无法遍历)
    // 弹出 出队 
    Nums.pop();
    cout << Nums.size() << endl;

    cout << Nums.front() << " " << Nums.back() << endl;
    
#pragma endregion

Deque

Day.cpp
 #pragma region deque
    // double end queue 双端队列  (队尾队头都可以插入)
    // 支持从中间插入,支持迭代器
    deque<int> Nums;
    Nums.push_back(100);
    Nums.push_back(200);
    Nums.push_front(10);
    Nums.push_front(20);

    Nums.pop_front();
    Nums.pop_back();

    // Nums.insert(--Nums.begin(), 500);  // 崩溃  --begin()不属于这个deque的内存   ++end()不行
    // 迭代器遍历
    for (auto It = Nums.begin(); It != Nums.end(); ++It)
    {
        cout << *It << endl;
    }
    cout << Nums.front() << " " << Nums.back() << endl;

    // 有十个评委打分(70-100)求选手最终得分(去掉最低分,去掉最高分,取平均值)
    // 0-30  % 31   + 70
    srand(time(0));
    deque<int> Nums;
    for (int i = 0; i < 10; ++i)
    {
        Nums.push_back((rand() % 31 + 70));
    }
    sort(Nums.begin(), Nums.end());
    Nums.pop_back();
    Nums.pop_front();
    int Sum = 0;
    for (auto It = Nums.begin(); It != Nums.end(); ++It)
    {
        Sum += *It;
    }
    cout << "平均分为:" << ((float)Sum / 8) << endl;

    cout << "end" << endl;
    
#pragma endregion

stack

Day.cpp
 #pragma region stack
    //// 栈  先进后出
    stack<int> Nums;
    Nums.push(100);
    Nums.push(50);
    Nums.push(200);

    cout << Nums.size() << endl;
    cout << Nums.top() << endl; // 获取栈顶的元素
    Nums.pop();
    cout << Nums.size() << endl;
    cout << Nums.top() << endl;
#pragma endregion

算法和Lambda表达式

Day.cpp
 struct Print
{
    void operator()(const int& Num)
    {
        cout << "-*- " << Num << " -*-" << endl;
    }
};

#pragma region 算法和Lambda表达式
    ////// 需要包含头文件
    vector<int> Nums;

    srand((unsigned int)time(0));
    for (int i = 0; i < 10; ++i)
    {
        Nums.push_back((rand() % 31 + 70));
    }

    ////// 第三个参数可以传一个仿函数,也可以传一个lambda表达式
    ////// 如果传的是仿函数,必须加(),如果是定义map  set<>不能带()

    ////// 第三种 Lambda表达式  [](参数)->返回值{}
    ////// [] 中可以加修饰符号 = & ,
    ////// 参数的类型和个数取决于Lambda表达式的实际功能
    ////// ->类型  返回值,如果返回值是void 可以省略
    ////// {}函数体

    ////// 仿函数  Lambda表达式  闭包
    sort(Nums.begin(), Nums.end(), [](int& Num1, int& Num2)->bool 
        {
            return Num1 > Num2;
        });
    cout << "End" << endl;

    ////// for_each
    ////// 遍历的算法
     for_each(Nums.begin(), Nums.end(), Print());
    for_each(Nums.begin(), Nums.end(), [](int& Num)
        {
            Num *= 5;
        });
    for_each(Nums.begin(), Nums.end(), Print());



    vector<string> Names1;
    Names1.push_back("LiLy");
    Names1.push_back("John");

    vector<string> Names2;
    Names2.push_back("张三");
    Names2.push_back("李四");
    Names2.push_back("王五");

    vector<vector<string>> Names;
    Names.push_back(Names1);
    Names.push_back(Names2);

    // Lambda表达式的参数是什么取决于容器中存储的是什么类型,可以扩展成& 和  const&
    for_each(Names.begin(), Names.end(), [](vector<string>& Name)
        {
            for_each(Name.begin(), Name.end(), [](string& Temp)
                {
                    cout << Temp << " ";
                });
            cout << endl;
        });

    //// 定义Person类,使用sort按照姓名进行排序,排序后使用for_each输出
    //
    vector<Person> Persons;
    Persons.push_back(Person(10010, "LiLei"));
    Persons.push_back(Person(10011, "ZhangSan"));
    Persons.push_back(Person(10012, "Ada"));
    Persons.push_back(Person(10013, "王丽"));
    Persons.push_back(Person(10014, "Blue"));
    Persons.push_back(Person(10015, "刘卓"));

    sort(Persons.begin(), Persons.end(), [](const Person& P1, const Person& P2)->bool 
        {
            return P1.GetName() < P2.GetName();
        });

    for_each(Persons.begin(), Persons.end(), [](const Person& P) 
        {
            cout << P.GetID() << ": " << P.GetName() << endl;
        });

    int ID = 10014;
    int Temp = 0;

    //// = 可以获取与函数平级的变量
    //// & 表示既可以访问,又可以修改
    auto Result =  count_if(Persons.begin(), Persons.end(), [=, &Temp](const Person& P)->bool 
        {
            Temp++;
            return P.GetID() < ID;

        });
    cout << Result << " " << Temp << endl;

    //// 给定的迭代器中任何一个符合条件,所有的都不符合就为假
    bool Result1 = any_of(Persons.begin(), Persons.end(), [=, &Temp](const Person& P)->bool
        {
            return P.GetID() > 10020;

        });
    cout << Result1 << endl;

    // 如果迭代器的范围都符合条件那么久为真,如果有任意一个不符合就为假
    bool Result2 = all_of(Persons.begin(), Persons.end(), [=, &Temp](const Person& P)->bool
        {
            return P.GetID() > 10012;

        });
    cout << Result2 << endl;
    
#pragma endregion

string字符串补充

Day.cpp
 
#pragma region string字符串补充
     //FString
     string Str = "Hello, World";
    Str += "火星时代"; // + 运算符是两个字符串的拼接
    Str.append("火星时代");

     cout << Str[5] << endl;

    // 字符串中文(单独打印字符会出问题)
    string Str1 = "火星时代abcv";
    for (int i = 0; i < Str1.size(); ++i)
    {
        cout << Str1[i];
    }

   // //// find查找子串,如果是英文和数字的话是一一对应,但是中文一个中文对应两个字符
   // //// 返回的是子串在整个字符串中的索引开始的位置
   // //// 如果子串没有找到,返回-1
    int Result = Str1.find("星b", 0);
    cout << Result << endl;

    // char Ch = '中'; //  2*8    
    wchar_t Ch1 = '中';
    cout << Ch1 << endl;
     cout << Str << endl;

    string Str = "Hello, World";
   // // 从哪开始,到哪结束,替换成xxxx
     Str.replace(1, 5, "火星时代");

   // // 从什么索引开始取,取多长
   // // 第二个参数的长度可以超过字符串的长度不会报错,直接取到字符串结束的位置
   // // ?cccyyyy  SubString(1, Str.size()) -》 cccyyyy
    string Str1 = Str.substr(3, 100);
    cout << Str1 << endl;
    
#pragma endregion

c语言格式化输出

Day.cpp
 #pragma region C语言格式化输出
    // 打印字符串
    printf("Hello\n火星时代\n");
    //// 打印变量 %d int    %f  float   %p  指针
    //// 占位符和要替换的变量类型必须统一,否则会出问题
    float Num = 100.556f;
    printf("Num: %f\n", Num);

    char C = 'a';
     cout << &C << endl;// 会乱码
    printf("C的地址:%p %d %f", &C, 50, Num);

     //对齐和小数位的控制
    int Num = 100;
    printf("%5d\n", Num); // 打印结果进行填充,不够的用空格代替
    printf("%-5d\n", Num); // 换另一种对齐方式

    float Height = 179.1256847f;
    // m.n   m代表总共显示的位数(包含小数点),n表示小数点后保留几位,m比较大会用空格补齐
    printf("%15.3f\n", Height);
    printf("%-15.3f\n", Height); // 换另一种对齐方式

    // printf不支持打印string类型
    string Str = "Hello World";
    printf("Value: %s", Str);

#pragma endregion

Day5

类型转换

Day.cpp
#pragma region 类型转换
    //// 类型转换
    //// 隐式转换   显式转换
    int Num = 10;
    float Num1 = 10.5f;
    Num1 = Num; // 范围小的值(int)赋值给范围大(float)的值  隐式转换
    Num = (int)Num1; // 范围大的值(float)赋值给范围小(int)的值  显式转换  10.6f 


    // C++的类型转换
    // static_cast 隐式转换 + 一部分显式转换
    // dynamic_cast 用在父类转化成子类 (必须有virtual的方法)
    // const_cast 把常量转化为变量
    // reinterpret_cast 完全不想管的类型转换(前面三个都失败的备选方案)

    // 把()中的变量,字面量转化成<>中的类型
    int Num = static_cast<int>(10.5f); // 显式转换
    char C = 96;
    int Num1 = static_cast<int>(C); // 隐式转换

    // Student S;
    
    //转换三要素
    // dynamic_cast  必须转化为引用或者指针,不能转化为普通类型
    // 要转化的父类和子类必须有多态virtual
    // 父类能够转化为子类的前提是父类对象指向的是子类的对象,如果指向的是一个父类,会转化失败
    Person& P = S;
    dynamic_cast<Student&>(P).TestStudent();
    
    Person P1;
    Student S2 = dynamic_cast<Student&>(P1);
    S2.TestStudent();

    // 如果没有virtual,使用dynamic_cast会转换失败,使用static_cast
    Person* P = new Student();
    Student* S = static_cast<Student*>(P);
    if (S) S->TestStudent();

    Student S1;
    Person* P = new Student();
    Person& P1 = S1;
    // 要转换的类型和括号中的参数类型一致(如果是指针,那么都需要是指针,如果是引用,参数是一个普通类型或者引用类型)
    Student& S = dynamic_cast<Student&>(*P);
    Student* PS = dynamic_cast<Student*>(P);
    Student* PS1 = dynamic_cast<Student*>(&P1);


    const int Num = 100;
    // const_cast中的类型需要是一个引用
    const_cast<int&>(Num) = 50; // 相当于给Num创建了一个备份,改的是备份的值,不影响原来的值
     
     cout << Num << endl;

    set<int> Nums;
    Nums.insert(500);
    Nums.insert(100);
    const_cast<int&>(*Nums.find(500)) = 100; // 改的就是集合中的值
    for (auto It = Nums.begin(); It != Nums.end(); ++It)
    {
        cout << *It << endl;
    }

    const int Num = 10;
    int* Ptr = const_cast<int*>(&Num);
    *Ptr = 100;
    cout << Num << " " << *Ptr << endl;


    int* Ptr = new int(97);
    long long* CPtr = reinterpret_cast<long long*>(Ptr);
    cout << *CPtr << endl;

#pragma endregion

C++11新特性

#pragma region C++11新特性
    set<vector<vector<int>>> Nums;
    //// auto 自动类型推导,根据=右边的值,自动推断=左边变量的类型
    //// 1)类型比较复杂,想偷懒
    //// 2)不确定类型的时候
    auto It = Nums.begin();
    auto Ptr = Test;
     auto Num; // 如果使用auto,那么必须赋值,不赋值推断不出类型


    //// 类型推断(根据变量或者函数返回值推断类型)
    float Num1 = 10.5f;
     decltype(Num1) Temp;
    //// 如果根据函数进行类型推断的时候,函数名()
    //// 根据函数推断类型,编译器特性,并没有执行函数中的代码
    decltype(Test1()) Temp1 = 10;

    // 根据括号中的内容[既可以是类型也可以是变量]推断类型相关的信息
    Person P;
    typedef int Int32;
    Int32 Num;
    cout << typeid(Num).name() << " " << typeid(Num).hash_code() << endl;


    int Nums[] = { 10, 20, 30, 40 };
    // 基于范围的for循环,相当于蓝图中的foreach
    for (int Num : Nums)
    {
        cout << Num << endl;
    }

    Person PS[] = { Person(), Person(), Person() };
    for (const Person& P : PS)
    {
        
    }

    for (const auto& P : PS)
    {
        
    }
    
#pragma endregion

工厂模式

// 简单工厂模式()抽象工厂模式
    // 工厂模式

int Test() {
	return 0;
}
//产品类
class ElecProduct { 
public:
	virtual void ShowProduct() = 0;
};
class PhoneProduct : public ElecProduct {
	virtual void ShowProduct() {
		cout << "This is a Phone";
	}
};
class PCProduct : public ElecProduct {
	virtual void ShowProduct() {
		cout << "This is a PC";
	}
};
// 工厂类
class ElecFactory {
public:
	virtual ElecProduct* CreateProduct() = 0;
};
class PhoneFactory : public ElecFactory {
	virtual ElecProduct* CreateProduct() override{
		return new PhoneProduct();
	}
};
class PcFactory : public ElecFactory {
	virtual ElecProduct* CreateProduct() override {
		return new PCProduct();
	}
};
enum class Selection {
	Phone,
	PC
};

#pragma region 工厂模式

	//面向对象 封装 继承 多态 谁不确定就抽象谁
	Selection clientSelection = Selection::PC;
	ElecFactory* ef = nullptr;

	switch (clientSelection)
	{
	case Selection::Phone:
		ef = new PhoneFactory();
		ef->CreateProduct()->ShowProduct();
		break;
	case Selection::PC:
		ef = new PcFactory();
		ef->CreateProduct()->ShowProduct();
		break;
	default:
		break;
	}


#pragma endregion

模板泛型

//泛型特化 - my
template <class T>
bool IsEqual(const T& Left, const T& Right) {
	return Left == Right;
}
template <>
bool IsEqual<string>(const string& Left, const string& Right) {
	cout << "字符串比较" << endl;
	return Left == Right;
}
template <>
bool IsEqual<long long>(const long long& Left, const long long& Right) {
	cout << "long比较" << endl;
	return Left == Right;
}
template <>
bool IsEqual<int>(const int& Left, const int& Right) {
	cout << "int比较" << endl;
	return Left == Right;
}
#pragma region 泛型

	//特化
	string Left = "hello";
	string Right = "wordl";
	cout << IsEqual<int>(1, 1) << endl;
	cout << IsEqual<long long>(1, 1) << endl;
	cout << IsEqual(Left, Right) << endl;

#pragma endregion

#pragma once


//泛型 Teacher
TemplateTest.h
int Add(int Num1, int Num2) { return Num1 + Num2; }
float Add(float Num1, float Num2) { return Num1 + Num2; }
template <typename T>
T Add(T Num1, T Num2)
{
	return Num1 + Num2;
}

#pragma region 模板泛型
   // // 泛型模板函数
   // // 只有类型不同,其他的地方都相同
   // // 
   // // 特殊写法    声明和实现都写到.h中, .hpp, 一般没有对应的cpp
   // // 
    int Result = Add<int>(10, 50);
    cout << Result << endl;
    cout << Add(10.5f, 20.6565f) << endl;

   // // T类型需要满足模板函数中的运算
    MyStruct MS1;
    MyStruct MS2;
    Add(MS1 , MS2);
    string Str1 = "Hello";
    string Str2 = "火星时代";
    cout << Add(Str1, Str2) << endl;
     cout << Add<int>(5, 10.5f) << endl;
    //泛型模板类
     string Str = "Hello" + "火星时代";
    
  

#pragma endregion

泛型成员指针

#pragma region 泛型成员指针
    // 成员函数指针
    Person* P1 = new Person(10010);
    Person P2 = Person(10012);
    // TestPtr(P1, &Person::PrintID);
    TestTemplatePtr<Person>(P2, &Person::TestPerson);


    MyStudent MS;
    TestTemplatePtr<MyStudent>(MS, &MyStudent::Test);
    // 泛型成员函数指针
#pragma endregion
//Person.h
#include "Person.h"

#include <iostream>

using namespace std;

Person::Person()
{
	ID = 0;
}

Person::Person(int ID)
{
	this->ID = ID;
}

void Person::TestPerson()
{
	cout << ID << " Person::TestPerson" << endl;
}

void Person::PrintID()
{
	cout << ID << endl;
}

void Student::TestStudent()
{
	cout << "Student::TestStudent" << endl;
}
//.cpp
#include "Person.h"

#include <iostream>

using namespace std;

Person::Person()
{
	ID = 0;
}

Person::Person(int ID)
{
	this->ID = ID;
}

void Person::TestPerson()
{
	cout << ID << " Person::TestPerson" << endl;
}

void Person::PrintID()
{
	cout << ID << endl;
}

void Student::TestStudent()
{
	cout << "Student::TestStudent" << endl;
}

//MyStudent.h.cpp
#pragma once
class MyStudent
{
public:
	void Test();
};
#include "MyStudent.h"
#include <iostream>

using namespace std;

void MyStudent::Test()
{
	cout << "MyStudent::Test" << endl;
}

 

posted @ 2024-03-18 17:24  啊賢  阅读(14)  评论(0编辑  收藏  举报