[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;
}