C++学习笔记

A.c++与c的区别

1.头文件

在这里插入图片描述
标准库变为
#include
#include <stdio.h> 正常引入也可
#include 前面加上c 后面去掉.h 也是可以的
//1.头文件发生改变
#include
#include<stdio.h>
#include

//2.定义一个命名空间
using namespace std;
namespace 厨房
{
int k = 99;
}
//3.命名空间的嵌套
namespace a
{
int j = 9;
namespace b
{
int h = 9;
}
}
int main()
{//空间写在函数外面就是全局变量
//访问空间中的值 空间::成员
//作用域分辨率 ::
printf("%d\n",厨房::k);
//但是这样太麻烦
//为了去掉前缀,引入using
using namespace 厨房;//作用是去掉 std::
printf("%d\n", k);

//嵌套
printf("%d",a::b::h);
using namespace a::b;
printf("%d", h);


return 0;

}

2.数据类型

汉字一个是2个字节
定义函数的时候,记得加括号
在这里插入图片描述
#include
#include
#include//c++中的字符串处理
#include//c语言中的字符串处理
using namespace std;//这句话必须要加,因为cin cout都在这个命名空间里面
struct girl
{ //数据成员:属性
char name[20];
int age;
//成员函数:行为
void print()
{
cout << name << " " << age << endl;
}

};
int main()
{
bool boolNum = 1;
//bool类型
//1.含义:真和假
//2.打印的值:0和1
//3.作用:开关,返回值
//4.特殊的初始化
//5.非零表示成立,-1也表示成立,0表示不成立
boolNum =true;
boolNum = false;
boolNum = -1;
printf("%d\n", boolNum);
//指针赋值变化 NULL->nullptr
int *ptr = nullptr;
//动态申请内存 malloc free-》new delete
//1.分配单一内存,指针变为普通变量
ptr = new int;
//2.分配一段内存
int *array = new int[10];// int array[10]
//3.申请内存并且初始化
int *a = new int(12);//普通变量小括号初始化
int *pArray = new int[10]{1, 2, 3};//数组指针大括号初始化
printf("%d\n", *(pArray+4));
//这里出现了优化。c语言不能在申请内存时同时初始化

delete a;
delete pArray;
delete[] array;//释放数组
delete ptr;//释放普通变量
//4.内存池,申请的内存可以在分配
char *malloc = new char[1024];//申请1024个字节
int *ray = new(malloc) int;//前面malloc 代表首地址 int 代表申请4个字节
char *pStr = new(malloc + 4) char[100];//了解再分配内存 类型 *指针名=new(首地址)类型[]
delete[] malloc;//直接释放总内存
//输入和输出
//输出 printf---> cout<<
//输入 scanf----> cin>>
//1.单个数据的输入和输出
int num = 0;//初始化还是一样的
char str[20] = "";//字符串
//不需要格式控制字符,变得简洁
printf("请输入一个num:");
cin>> num;
cout << num;
printf("请输入一个字符串str;");
cin >> str;
cout << str<<endl;
//2.cout 原样输出,同时支持字符串
cout << "I love you\\t\n";
//3,输出多个数据
//endl->"\n"多出一个功能,清空缓冲区
cout << "i love you" << "\t" << num << str << endl;
cin >> num >> str;
cout << num << str;
//4,结构体
//1.内部可以存在函数
//2.用到结构体类型,不需要用struct
girl Mygirl = { "baby", 100 };
//3.概念性的东西,属性,行为
//4.访问函数和访问结构体成员是一样的行为
Mygirl.print();//访问函数
//string的基本使用
//string并不是c语言中的字符串
//1.基本创建
string str0;
string str1("hua");
string str2 = "huaewf";
string str3(str1);//也可以串变量和常量
//基本操作
string str5= str1 + str2;
cout << (str5> str2) << endl;
cout << (str5== str2) << endl;
cout << (str5< str2) << endl;
//C++中的string转换为c语言中的字符串;
printf("%s\n", str5);//输出乱码,因为c++中的string不是字符串
printf("%s\n", str5.c_str());//c_str()返回字符串首地址

system("pause");
return 0;

}

3.函数思想转变

#include
using namespace std;
/*
内敛函数:二进制代码形式存在,牺牲空间,提高效率 短小
inline 或者在结构体中 或者 在类中实现的函数

函数重载:允许同名不同参函数存在
三个不同参:
数目不同
类型不同
顺序不同

函数缺省:即给参数初始化 重载的集合体
注意问题:从右往左不能留空

*/
inline int Max(int a, int b)
{
return a > b ? a : b;
}
//数目不同
int Max(int a, int b, int c)
{
return a + b + c;
}
//类型不同
char Max(char a, char b)
{
return a > b ? a : b;
}
//顺序不同,一定有不同类型
void print(char a, int b)
{
cout << a << " " << b<<endl;
}
void print(int a, char b)
{
cout << a << " " << b;
}
//函数缺省 从右往左
void function(int a, int b = 3, int c = 4)
{
cout << a + b + c << endl;
}
int main()
{
print(‘A’, 12);
print(12, ‘A’);
//没有注明是几,则使用默认值
//缺省能够实现同一函数的不同调用形式
function(1);
function(2, 3, 4);

system("pause");
return 0;

}

4.C++中的引用 int &形参=实参

#include
using namespace std;
void Modify(int *a)
{
*a = 100;

}
void modify(int &num)
{
num = 12;
}
//输入常数的两种方法
void print(const int &nam)
{//const 不能改变形参的值
cout << nam << endl;
}
void Print(int &&nam)
{
cout << nam << endl;

}
struct girl
{
char name[20];
int age;
int getAge()
{
return age;
}

};
//不能返回局部变量
int get()
{
int num;
return num;//因为局部变量会在使用后释放内存,无法返回
}
int main()
{//引用 &
//起别名
int num = 0;
int &sf = num;//int &形参=实参 则&形参=实参
sf = 2;//sf 和num指向同一空间 ,修改sf就等于修改num
cout << num << endl;
//用在哪里呢
//1.当需函数的返回,防止拷贝本的产生,真正改变实参
//在C语言中,使用指针改变实参
//c++中,使用引用来改变
int d = 8;
modify(d);
cout << d << endl;
/*int *d = 8;
Modify(d);/
//modify(1)会出错 int &形参=实参; 形参必须是标识符
//想要输出常数
print(2);
Print(2);
//2.当做函数返回,返回一个变量,增加左值使用
girl myGirl = { “花花”, 20 };
myGirl.age = 18;
cout << myGirl.age << " " <<myGirl.name<< endl;

/*int k= get();
cout << k << endl;*/// 错误用法

system("pause");
return 0;

}

5.结构体中的构造函数

#include
#include
using namespace std;
//面向对象的方式写一个链表
//c++特殊的函数:构造函数
// 1.名字和结构体名称相同;
// 2.没有返回值
// 3.结构体变量被创建的时候调用;
struct MM
{
string name;
int age;
//构造函数 作用:为基本数据成员初始化
MM(string nameM, int ageM)//这里以后会讲 不能写成跟原来一样
{
name = nameM;
age = ageM;
cout << “调用构造函数的过程” << endl;
}
void print()
{
cout << name << " " << age << endl;
}
};
void print(struct MM mm)
{
cout << mm.name << " " <<mm.age<< endl;

}
int main()
{//构造函数决定了结构体变量的类型
MM mm = { “花花”, 12 };
MM mm2(“憨憨”, 13);//c++初始化采用调用函数的过程
//C++面向对象的方式,
//行为是描述对象的
mm.print();//C++先创建对象,然后调用行为
//C语言一般是面向过程,都是行为操控对象
print(mm);//c语言行为调用对象

return 0;

}

6.C++的无头链表

#include
using namespace std;
/*
无头链表
/
struct Node
{
int data;
struct Node
next;
Node()
{
next = nullptr;
}
Node(int dataA)
{
data = dataA;
}
Node(int dataA,Node* nextA)
{
data = dataA;
next = nextA;
}
};
struct list
{
Node* froNode;//不加struct
int size;
list();//构造函数
void insertBt(int data);
void printList();
};
//在结构体外面定义函数
list::list()
{
froNode = NULL;
size = 0;

}
void list::insertBt(int data)
{
froNode = new Node(data, froNode);//new 一个结构体//连接操作
//用一个构造函数就封装好了连接
/*1.next指向nextA,即froNode,即Null;
2.然后froNode又指向新创建的这个节点的首地址
*/

}
void list::printList()
{
Node* pMove = froNode;//粗心大意了,应该是不为空时
while (pMove)
{
cout << pMove->data << endl;
pMove = pMove->next;
}
}
int main()
{
list* pList = new list; //不懂
pList->insertBt(1);
pList->insertBt(1);
pList->insertBt(1);
pList->printList();

return 0;

}

7.this指针

#include
#include
using namespace std;
struct girl
{
string name;
int age;
girl(string name, int age)
{//当形参的名字和实参的名字相同时
this->name = name;
this->age = age;
}
girl getGirl()这里也不懂
{
return *(this);//返回这个类
}
void print()
{
cout << name << " " << age << endl;
}
};
int main()
{
girl *pGirl = new girl(“花花”, 12);
cout << pGirl->getGirl().getGirl().getGirl().age<<endl;有点不懂
//符合语法,实质是对自身进行递归

system("pause");
return 0;

}

2.C++类和对象

新学习到的知识:
char * str= “Hello World”;字符指针
char str[ ]=“Hello World”;字符数组
都可以储存字符串
char str= ‘ A’;字符
——————————————————————

#include
#include
using namespace std;
class person
{
//1.class和struct都可以定义类
//struct 默认公有
//class 默认私有
//2.private,public,protected
//3.在类的外面实现成员函数定义 作用域分辨符:: 函数名前加
private://在类的外部不能调用内部
public:
//行为 吃饭
void eat()
{
cout << “吃饭” << endl;
}
void drink()
{
cout << “喝水” << endl;
}
int person::getAge()
{
return age;//private可以内部访问,但是不能外部访问
}
const char* getName();

	/*void set(int ageA,string nameA)
	{
	age = ageA;
	name = nameA;
	}*/
	person(int age = 3, string name = "花花")
{
	this->age = age;
	this->name = name;
}


//属性

private://属性设置为公有不安全,任何对象都能访问
//所以一般设置为私有
int age;
string name;
//protected:保护的,在类的继承中起作用
};

const char* person::getName()
{
return name.data();//完全不懂
}
int main()
{
person 黄飞鸿(2,“花花”);

黄飞鸿.eat();
cout << 黄飞鸿.getAge() << " " << 黄飞鸿.getName() << endl;
cout << sizeof(string) << endl;
cout << sizeof(person) << endl;

return 0;

}
———————————————————————————————
#include

using namespace std;
#define MAX(a,b)((a)> (b) ? (a) : (b))
inline int max(int a, int b)//加了inline就不用挑了
{
return a > b ? a : b;//函数这种就需要跳出来运行 ,在跳回去
}
//内联函数 使用关键字 inline 放在返回值类型前面
//1.可以用来替换宏函数,在编译期间,直接替换到调用处
//2.减少开销 不用跳
int main()
{//比较两个数的大小
int a = 4, b = 9;
int mmax = max(a, b);

return 0;

}

1.构造函数和析构函数

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include<string.h>
using namespace std;
class Stu
{
public:
/*构造函数和析构函数同级调用顺序:
和栈一样:(一个碗) 构造函数:先来先调用 -->入栈
析构函数: 后来先调用—>出栈

*/
//构造函数,函数名和类名相同  没有返回类型
//类型:
//1.无参构造(默认构造)
//2.有参构造
//3.拷贝构造

Stu()
{
	m_age = 10;
	name=(char*)malloc(sizeof(char)* 13);//动态申请内存
	strcpy(name, "NUL");
	cout << "我是构造函数" << endl;

}
//重载函数 重名
Stu(int tage,  char* tname)
{
	m_age=tage ;
	name = (char*)malloc(strlen(tname)+1);//确切的空间大小 记得加\0这个1
	//这里要注意 malloc里面要写大小 ,那么里面也可sizeof(char)*strlen(tname)+1
	strcpy(name, tname);
	cout << "我是构造函数" << endl;
}
//析构函数 释放内存
//没有参数 也没有任何返回类型
//在主函数完成后自动调用
~Stu()
{
	if (name != NULL)
	{
		free(name);
		name = NULL;
	}
	cout << "我是析构函数" << endl;
}

int getAge()
{
	return m_age;
}
char* getName()
{
	return name;
}

private:
int m_age;
char* name;
};
int main()
{

Stu maye;//无参构造函数,不需要写括号
cout << maye.getName() << " " << maye.getAge() << endl;
//有参构造调用方法
//1.直接在对象后面
Stu newy(28, “慕容”);
cout << newy.getName() << " " << newy.getAge() << endl;
//2.创建列表
Stu cc = { 56, “画画” };
cout << cc.getName() << " " << cc.getAge() << endl;
//3.通过匿名对象初始化
Stu(34, “哗哗”);//无名创建 如果没有接 执行完构造函数,立即执行析构函数
//生命周期取决于如何处理(如何后接)
//如果用有名对象去接,他就会直接转正,不会立马释放,当有名对象生命周期结束,才会释放(正常了)

Stu xoy = Stu(28, "佐助");
cout << xoy.getName() << " " << xoy.getAge() << endl;
//浅拷贝
//编译器自己实现的是浅拷贝,我们自己实现深拷贝
//Stu 成毅(30, "司凤");
//Stu 司凤 = 成毅;//把成毅拷贝给了司凤
//成毅.setName("花花");
//cout << 成毅.getName() << endl;
//cout << 司凤.getName() << endl;










cout << "我是分隔符" << endl;
return 0;
//返回0之后析构

}在这里插入图片描述

2.拷贝构造函数

#include
using namespace std;
class aaa
{
public:
aaa()
{
a = 0;
}
aaa(int a)
{
this->a = a;
}
//如何自己去写拷贝构造函数
aaa(aaa& other)//加& 不报错 为啥 只能长这个样子
{
a = other.getA();

}

int getA()
{
	return a;
}

private:
int a;
};
int main()
{
aaa tt;
cout << tt.getA() << endl;
aaa t(2);
cout << t.getA() << endl;//如果没有写构造函数,会自动生成一个构造函数返回乱码
//用一个对象去初始化另一个对象,需要拷贝构造函数
//如果没有写拷贝构造函数,编译器会自动给我们一个拷贝构造函数
//1.
aaa t1 = t;//初始化
cout << t1. getA() << endl;
//2.
aaa t2(t);
cout << t2.getA() << endl;
//无名对象初始化 会调用拷贝构造函数吗? 不会调用
aaa t3 = aaa(23);//无名对象直接转正,获得姓名t3
cout << t3.getA() << endl;

aaa 新建;
新建 = t;  //赋值  //这里需要拷贝构造函数吗? 不需要,所需为运算符重载=
//初始化和赋值是不一样的
//初始化:在定义的同时赋值
//赋值:在初始化后赋值


return 0;

}

3.浅拷贝和深拷贝

在这里插入图片描述

在这里插入图片描述
1.浅拷贝知识拷贝类,但没有拷贝空间,指针指向同一区域,在释放内存时,出现问题中断,前面都放掉了,下一个无法释放、
在这里插入图片描述

4.类的组合

在这里插入图片描述
class A
{
public:
A()
{
}
A(int
a)
{
m_a = a;
}

int getA()
{
	return m_a;
}

//private:
int m_a;
};
class B
{
public:
B(int b, A other)
{
m_b = b;
//m_ba = other;//不是初始化的方式 我们还没有接触到等号重载
}

//private:
int m_b;
A m_ba;
};
对应:B b(20, A(30));

class A
{
public:

A(int a)
{
	m_a = a;
}

int getA()
{
	return m_a;
}

//private:
int m_a;
};
class B
{
public: //我们并不需要默认,但他就是报错,怎么办
B(int b, int a) :m_ba(a) //组合类,这样做就可以了
{
m_b = b;
//m_ba = other;//不是初始化的方式 我们还没有接触到等号重载
}
//private:
int m_b;
A m_ba;
};
对应:B b(20, 30);

#include
using namespace std;
class A
{
public:

A(int a)
{
	m_a = a;
}
~A()
{
	cout << "A的析构函数" << endl;
}

int getA()
{
	return m_a;
}

//private:
int m_a;
};
class B
{
public://我们并不需要默认,但他就是报错,怎么办?
B(int b, int a,int ta) :m_ba(a),maye(ta) //组合类,使用参数列表
{//使用参数列表的两种情况:
//1.别的类
//2.const 属性
// maye = ta;//错误,因为不能对常量进行赋值
m_b = b;
//m_ba = other;//不是初始化的方式 我们还没有接触到等号重载
}
~B()
{
cout << “B的析构函数” << endl;
}
//private:
const int maye;
int m_b;
A m_ba;

};
int main()
{
B b(20, 30,56);
cout << b.m_b << " " << b.m_ba.m_a <<b.maye<< endl;
//思考:先执行谁的构造函数,是本类还是组合类?
//结论:先执行组合类的,然后执行本类
//先执行谁的析构函数? 跟构造函数相反 先执行本类 在执行组合类

//如果有多个类组合,先定义的先执行构造,后定义的后执行构造,与参数顺序无关



return 0;

}

const char* str 传参

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
#include
#include
using namespace std;
class My
{
public:
/My(int size = 0) :size(size)
{
c_str = (char
)malloc(size + 1);
strcpy(c_str, “”);
}*/
My()
{

}
My(int size,char* str)
{
	this->size = size;
	strcpy(c_str, str);//字符串的比较和赋值都需要用函数
}
//深拷贝
My(const char* str)
{
	size = strlen(str);
	c_str = (char*)malloc(size + 1);
	strcpy(c_str, str);

}
//拷贝构造 固定模式
My(const My& other)
{
	size = other.size;
	c_str = (char*)malloc(size + 1);
	strcpy(c_str, other.c_str);
}
~My()
{
	if (c_str != NULL)
	{
		free(c_str);
		
	}
}
//设置字符串
void setStr( char* str)
{
	strcpy(c_str, str);
}
//连接
char *mycat(const My& other)
{
	//要考虑,连接进去的内存是否足够
	if (other.size == 0)
	{
		return c_str;
	}
	else
	{
		//先定义一个临时变量来储存字符串
		char* temp = (char*)malloc(size + 1);
		strcpy(temp, c_str);
		free(c_str);

	    c_str = (char*)malloc(size + other.size + 1);
		strcpy(c_str, temp);
		strcat(c_str, other.c_str);
		
		
		free(temp);//释放临时变量


	}
	return c_str;
}
//重载
char *mycat(const char* str)
{
	//要考虑,连接进去的内存是否足够
	if (strlen(str) == 0)
	{
		cout << "啥也没呀" << endl;
	}
	else
	{
		//先定义一个临时变量来储存字符串
		char* temp = (char*)malloc(strlen(str) + 1);
		strcpy(temp, str);
		free(c_str);

		c_str = (char*)malloc(strlen(str)+ 1);
		strcpy(c_str, temp);
		

		free(temp);//释放临时变量

	}
	return c_str;
}
//拷贝
char *mycopy(const char* strr)
{
	strcpy(c_str, strr);
	return c_str;
	
}
//比较
int mycmp(const My& other)
{
	return strcmp(c_str, other.c_str);
}
//翻转
const char* reverse()
{
	for (int i = 0; i < size/2; i++)//注意这里一定要只弄一半 因为否则换后半部分又换换回来了
	{

		char ch = c_str[i];//每次先保存这个字符
		c_str[i] = c_str[size - i - 1];
		c_str[size - i - 1] = ch;
		
	}
	return c_str;
}
//获取字符串
const char* str()
{
	return c_str;
}

private:
int size;
char* c_str;
};
int main()
{
My Mystr(“环环”);
/My Mystr = new My;*/

cout << Mystr.str() << endl;
Mystr.setStr("花花");
My t = Mystr; //如果你不自己构造深拷贝,编译器会自动执行浅拷贝,则字符串指针指向同一空间,析构时出现bug。
cout << t.str() << endl;
/*char* a = "huahua";
char* b = "HUAU";
cout << strcat(a, b) << endl;*/
My sg("欢欢");
sg.mycat(Mystr);
cout <<sg.str() << endl;
sg.mycat("哈哈");
cout << sg.str() << endl;
sg.mycopy("拷贝");
cout << sg.str() << endl;
My 杨超越("1234567"); 
	杨超越.reverse();
cout << 杨超越.str() << endl;




return 0;

}

动态内存分配

#include
using namespace std;
class MyClass
{
public:
MyClass(int maye = 22) :maye(maye)
{

}

int getNum()
{
	return maye;
}
~MyClass()
{
	cout << "我是析构函数" << endl;
}

private:
int maye;

};

int main()
{ //申请普通变量
int *pi = new int;
*pi = 520;
cout << *pi << endl;
delete pi;

	//申请的同时初始化
	int *pii = new int(520);		
	cout << *pii << endl;
	delete pii;

	//申请数组 一段内存
	int *arr = new int[10]{1,23,4,5};//2. 大括号初始化 但这种方式只能用于基础数据类型 对象的数组会有问题
	for (int i = 0; i < 10; i++)
	{
		//  *(arr + i) = i;//1.指针赋值方式
		cout << arr[i] <<" ";
	}
	//delete arr;//不对
	delete[] arr;//释放数组 要加中括号

	//new 对象 会自动调用构造函数
	MyClass *pm = new MyClass(33);
	cout << pm->getNum() << endl;
	delete pm;//释放会直接调用类的析构函数

	//输出乱码 malloc仅仅开辟了空间,但没有调用构造函数,free也不调用析构函数
	//所以在c++中,我们常用new/delete来代替malloc/free,在类的使用中更是尤其
	MyClass *pp = (MyClass*)malloc(sizeof(MyClass));
	cout << pp->getNum() << endl;
	free(pp);
	//注意:只有数组在释放时,使用【】
return 0;

}

静态成员变量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
#include
using namespace std;
class Stu
{
public:
Stu(int age = 10) :age(age)
{
size++;
}
~Stu()
{

}
int getAge()
{
	return age;

}
int getNum()
{
	return size;
}
static int size;//班级人数

private:
int age;
//这里只是声明静态成员,声明必须在类的里面

};
//初始化类的静态变量,必须在类的外面
int Stu::size = 0;//只用声明的时候加static
//静态变量 一定要初始化 全局变量 不初始化 默认0

int main()
{
Stu VIP优酷[19];//申请数组的时候,每一个对象会自动调用构造函数
cout << VIP优酷[0].getAge() <<" "<<VIP优酷[0].getNum()<< endl;
//如何统计全班人数,每个人都知道,并且人数是一样的
//班上明明有19个人,为啥只显示1个?每个对象内存空间是独立的,互不影响
//怎么才能让每一个同学共享班级属性? 使用static 静态变量

//两种方式访问静态变量
cout<<VIP优酷[0].size<<endl;//1.
cout << Stu::size << endl;//2.内存不随对象的创建和消毁而改变 属于类



return 0;

}

静态成员函数

在这里插入图片描述
#include
using namespace std;
class Stu
{
public:
Stu(int age = 10) :age(age)
{
size++;
}
~Stu()
{

}
int getAge()
{
	return age;

}
static int getNum()//静态函数
{
	//age;//静态函数只能访问静态变量,不能访问普通变量
	return size;
}
static int size;//班级人数

private:
int age;
//这里只是声明静态成员,声明必须在类的里面

};
//初始化类的静态变量,必须在类的外面
int Stu::size = 0;//只用声明的时候加static
//静态变量 一定要初始化 全局变量 不初始化 默认0

int main()
{
Stu VIP优酷[19];//申请数组的时候,每一个对象会自动调用构造函数
cout << VIP优酷[0].getAge() <<" "<<VIP优酷[0].getNum()<< endl;
//如何统计全班人数,每个人都知道,并且人数是一样的
//班上明明有19个人,为啥只显示1个?每个对象内存空间是独立的,互不影响
//怎么才能让每一个同学共享班级属性? 使用static 静态变量

//两种方式访问静态变量
cout<<VIP优酷[0].size<<endl;//1.
cout << Stu::size << endl;//2.内存不随对象的创建和消毁而改变 属于类
//静态函数调用两种方法
cout << VIP优酷[0].getNum() << endl;
cout << Stu::getNum() << endl;



return 0;

}

面向对象

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
const加的位置不同,不一样
在这里插入图片描述

函数指针

#include
using namespace std;
class A
{public:
int j;
int k;
int l;

};
class B
{
public:
int j;
int dd;
int q;
static int h;
};
class Test_m
{

public:
Test_m(int a)
{
m_t = a;
}
//const 加在类型前后 都是修饰返回值
int getT() const //加在函数名后面 修饰的是this指向指向的对象不可修改
{
//this->m_t = 3; this 是一个const指针,指向正在调用的对象,前面自带const
return m_t;
}
Test_m& getThis()
{
return this;
}
static void print()
{
cout << “这是一个测试类” << endl;
}
private:
int m_t;
};
int add(int a, int b)
{
return a + b;
}
//c语言 实现相同功能
struct Test
{
int m_a;
};
void Test_init(Test
const pthis,int a)
{
pthis->m_a = a;
}
int Test_getT(Test* const pthis)
{
return pthis->m_a;
}
void print()
{
cout << “这是一个测试类” << endl;
}

int main()
{
int a = 4;
int b = 2;
add(a, b);//我们会发现面向对象 就是数据和操作(函数)分开声明。
//只有在调用函数时,数据才会和操作有联系。
//对象里面只有数据,没有函数,函数储存在代码段里面。
//而且类没有内存,只是1个类型,对象才有内存
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;//静态变量储存在全局数据 作用域在类里

Test_m AA(3);
AA.getT();
Test_m::print();
printf("_________________________\n");

Test zc;
Test_init(&zc,99);
Test_getT(&zc);
print();
printf("-------------------------\n");

cout << AA.getThis().getThis().getT()<<endl;//链式
cout << AA.getT() << endl;//const

return 0;

}

#include
using namespace std;
class MyClass
{
public:
MyClass(int a = 0) :a(a)
{

}
void show()
{
	cout << a << endl;
}
//不管是友元类还是友元函数,都破坏了类的封装性,不建议使用
friend class B;//友元类
//friend void print(MyClass AA);//友元函数 friend前缀声明 访问非公有成员

private:
int a;
};
//void print(MyClass AA)
//{
// AA.a = 456;
// cout << AA.a << endl;
//
//}
class B
{
public:
B(const char* ch)
{
this->ch = new char[strlen(ch) + 1];//重点:指针要存储一串数据就动态申请
strcpy(this->ch, ch);
}
void set(MyClass a)
{
a.a = 888;
aaa.a = 111;
}
char *ch;

MyClass aaa;

};
int main()
{
//MyClass *pp=new MyClass(23);
//pp->show();
///*print(pp);/
//cout << “---------------------”<<endl;
//MyClass 琉璃(99);
//B 禹司凤(“琉璃”);
//cout << 禹司凤.ch<< endl;
//禹司凤.set(琉璃);
//cout << 禹司凤.ch << endl;

void (MyClass::*pfun)();//函数指针
pfun = &MyClass::show;
//MyClass::show();
//调用函数指针必须要有对象
MyClass zc;
//pfun.show()//x

//(*pfun)();//x
//(MyClass::*pfun)();//x

//函数指针
(zc.*pfun)();//1.

MyClass* pa = new MyClass;//2.
(pa->*pfun)();



return 0;

}

知识点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

运算符重载

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
#include
using namespace std;
//运算符重载其实就是函数
class GirlFriend
{
public:
GirlFriend(int age = 18, int money = 10000) :age(age), money(money){};
int getAge()
{
return age;
}
int gerMoney()
{
return money;
}
void show()
{
cout << age << " " << money << endl;
}
//成员函数
GirlFriend girladd(GirlFriend g2)//其实有两个参数,前面隐藏了this GirlFriend girladd(this,GirlFriend g2)
{

	return GirlFriend(this->age + g2.age, this->money + g2.money);
}
//重载双目 +
GirlFriend operator+ (GirlFriend g2)//其实有两个参数,前面隐藏了this  GirlFriend girladd(this,GirlFriend g2)
{

	return GirlFriend(this->age + g2.age, this->money + g2.money);
}
//比较
bool operator==(GirlFriend g2)
{
	return this->age == g2.age&&this->money == g2.money;
}

private:
friend GirlFriend girladd(GirlFriend g1, GirlFriend g2);
/friend GirlFriend operator+(GirlFriend g1, GirlFriend g2);/
int age;
int money;

};

GirlFriend girladd(GirlFriend g1, GirlFriend g2)
{

return GirlFriend(g1.age + g2.age, g1.money + g2.money);

}
//运算符重载全局函数
//GirlFriend operator+(GirlFriend g1, GirlFriend g2)
//{
//
// return GirlFriend(g1.age + g2.age, g1.money + g2.money);
//}
int main()
{//看来operator+只能弄一个。
//双目操作符重载,
GirlFriend g1, g2;
//GirlFriend g3 = g1.girladd(g2);
//GirlFriend g3 = g1.operator+(g2);
GirlFriend g3 = g1 + g2;
g3.show();
//g1 + g2;
//函数实现
/GirlFriend self=girladd(g1,g2);
cout << self.gerMoney() << " " << self.getAge()<<endl;
/
//运算符重载全局函数
//GirlFriend self = operator+(g1, g2);
GirlFriend self = g1 + g2;
cout << self.gerMoney() << " " << self.getAge() << endl;

cout<<g1.operator==(g2)<<endl;

return 0;

}

在这里插入图片描述
在这里插入图片描述
#include
using namespace std;
class money
{
public:
money(int rmb = 10000, int dollar = 10000):rmb(rmb),dollar(dollar) {}
money()
{
rmb = 10000;
dollar = 10000;
}

void show()
{
	cout << rmb << "  " <<dollar<< endl;
}
~money()
{

}
//成员函数
void operator<<(ostream& out) //this在左边 是左操作符  右操作符是我们的重载
{
	out << dollar << "  " << rmb << endl;
	//ostream 是输出流,cout和out都是一个类
}

private:
friend ostream& operator<<(ostream& out, money& m);
friend money operator++(money& m);
friend money operator++(money& m,int);

friend money addMoney(money m);

int rmb;
int dollar;

};

//全局函数
money addMoney(money m)
{//访问私有属性 使用友元函数
m.dollar += 1000;
m.rmb += 1000;
return m;
}
//前缀 前置++
money operator++(money& m)
{//访问私有属性 使用友元函数
m.dollar += 1000;
m.rmb += 1000;
return m;
}
//后置++ 怎么区分前置和后置++ 为了区分 我们可以在后置++的参数里加一个int 标识 不能是其他,也不能传参只是一个标识
money operator++(money& m,int)
{//访问私有属性 使用友元函数
m.dollar += 1000;
m.rmb += 1000;
return m;
}
全局运算符重载函数
ostream& operator<<(ostream& out, money& m)
{
out << m.dollar << " " << m.rmb << endl;
return out;
}
int main()
{

/*money m1, m2;
money m3 = sub(m1, m2);
m3.show();*/

money m1(200, 111);
money m=addMoney(m1);
m.show();
money mm(2,23);
/*money r = operator++(mm);*/
money r = mm++;
mm.show();

//重载<< >>
/*show(cout, mm);*/
//mm << cout;//所以必须这样写,有点奇葩
cout<< mm << endl;
operator<<(cout, mm) << "maye"<<endl;//前面返回1个out 可以理解为返回1个cout




return 0;

}

类的继承

在这里插入图片描述

在这里插入图片描述

访问权限控制

在这里插入图片描述
在这里插入图片描述

能否被访问&&继承方式选择

在这里插入图片描述

#include<iostream>
using namespace std;
class Base//base 基类  老爹
{public:
	int a;//老爹的名字,大家都知道,都可以用
protected://专门用在继承中
	int b;//家里的钱,只能家里的人用
private:
	int c;//老爹的秘密,只有老爹能用
};

//三种继承方式
//public:常用这个, 能在类的内部访问,也能在类的外部访问
//protected:以私有方式继承,所以的成员都会被继承,但是基类的private不可见,其他的属性都属于子类的私有属性
//private:
class Derive:public Base//继承  儿子
{
public:
	void setA()
	{
		a = 12;//在子类的内部,可以被访问
		b = 99;//可以被访问
		//c = 23;//不能被直接访问
		
		cout << a << endl;
	}
protected://专门用在继承中
	
private:
	//相当于a,b都在这里
};
int main()
{
	Derive der;
	der.setA();
	der.a;//yes
	//der.b;//no 只能在子类中使用
	//der.c;//no 私有



	return 0;
}
#include<iostream>
using namespace std;
class Base//base 基类  老爹
{public:
	int a;//老爹的名字,大家都知道,都可以用
protected://专门用在继承中
	int b;//家里的钱,只能家里的人用
private:
	int c;//老爹的秘密,只有老爹能用
};

//三种继承方式
//public:常用这个, 能在类的内部访问,也能在类的外部访问
//protected:以私有方式继承,所以的成员都会被继承,但是基类的private不可见,其他的属性都属于子类的私有属性
//private:
class Derive:public Base//继承  儿子
{
public:
	void setA()
	{
		a = 12;//在子类的内部,可以被访问
		b = 99;//可以被访问
		//c = 23;//不能被直接访问
		
		cout << a << endl;
	}
protected://专门用在继承中
	
private:
	//相当于a,b都在这里
};
int main()
{
	Derive der;
	der.setA();
	der.a;//yes
	//der.b;//no 只能在子类中使用
	//der.c;//no 私有



	return 0;
}

继承的兼容性

#include<iostream>
#include<string>
using namespace std;
class Parent
{public:
	int age=12;
	void get爱()
	{= "司凤";
		cout << "叮咚!你收到了成毅哥哥的爱哦!!" <<<<endl;
	}
protected:
	string 爱;
private:


};
class Child:public Parent 
{public:
	void show()
	{
		cout <<<< "爱你爱你" << endl;
	}

};
void print(Parent jj)
{
	jj.get爱();
}
//子类对象可以当作父类对象使用
//.子类对象可以直接赋值给父类对象
//.子类对象可以直接初始化父类对象
//.父类指针可以直接指向子类对象
//.父类引用可以直接引用子类对象

int main()
{//.子类对象可以直接初始化父类对象
	Child ch;
	/*ch.get爱();*/
	Parent pa=ch;
	/*cout << pa.age << endl;*/
	pa.get爱();
//需要父类参数的函数,可以直接传子类对象进去
	print(ch);
//.父类指针可以直接指向子类对象
	Parent *pp= &ch;
	pp->get爱();
	//.父类引用可以直接引用子类对象
	Parent& ai = ch;
	ch.show();
	ai.get爱();

	while (1);//system("pause")//防闪退

	return 0;
}

在这里插入图片描述
在这里插入图片描述

//继承中的构造和析构
#include<iostream>
using namespace std;
class A
{
public:
	A(int a, int b)
	{
		this->a = a;
		this->b = b;
		cout << "父类构造函数" << endl;
	}
	 void showA()
	{
		 cout << a << " " << b<<endl;
		 
	}
	 ~A()
	 {
		 cout << "父类析构函数" << endl;
	 }
protected:
	int a;
	int b;
private:

};
class B:public A
{
public:
	B(int aa, int ab, int ac) :/*a(aa),b(ab)*/A(aa, ab), c(ac)//通过初始化参数列表的方式,显示的调用父类的构造函数
	{
		/*a = aa;
		b = ab;
		c = ac;*/
		cout << "子类构造函数" << endl;
	}
	void showB()
	{
		cout << a << " " << b << " " << c << endl;
	}
	~B()
	{
		cout << "子类析构" << endl;
	}
protected:
	int c;
private:

};
int main()
{
	B ha(1, 2, 3);
	ha.showA();
	ha.showB();



	return 0;
}

在这里插入图片描述

//继承中的构造和析构
#include<iostream>
using namespace std;
class A
{
public:
	A(int a, int b)
	{
		this->a = a;//这里是赋值,不是初始化
		this->b = b;
		cout << "父类构造函数" << endl;
	}
	 void show()
	{
		 cout << a << " " << b<<endl;
		 
	}
	 ~A()
	 {
		 cout << "父类析构函数" << endl;
	 }
protected:
	int a;
	int b;
private:

};
class B:public A
{
public:
	B(int aa, int ab, int ac) :/*a(aa),b(ab)*/A(aa, ab), c(ac)//通过初始化参数列表的方式,显示的调用父类的构造函数
	{
		/*a = aa;
		b = ab;
		c = ac;*/
		cout << "子类构造函数" << endl;
	}
	void show()
	{
		cout << a << " " << b << " " << c << endl;
	}
	~B()
	{
		cout << "子类析构" << endl;
	}
protected:
	int c;
private:

};
int main()
{
	/*B ha(1, 2, 3);
	ha.showA();
	ha.showB();*/


	//继承中同名成员使用
	B test(34,32,31);
	test.show();//子类会覆盖父类,调用子类中的成员
	test.A::show();//必须调用父类,使用分辨符::



	return 0;
}

要使用同名的属性,也要这样
在这里插入图片描述
在这里插入图片描述

#include<iostream>
using namespace std;
class A
{
public:
	static int num;//声明了静态变量。所有派生类中都会有这个静态变量
};
class B:public A
{
public:
	int getNum()
	{
		return this->num;
	}
};
 int A::num = 88;//不仅仅是初始化,更重要的是告诉编译器分配内存
int main()
{
	B 琉璃;
	//下面这3种方式都可以调用num
	琉璃.num = 99;
	A::num;
	B::num;

	cout<<琉璃.getNum();//建立对象的时候不会给静态变量分配内存,所以要初始化分配给他内存

	return 0;
}

多继承

菱形继承(virtual 防止二重义)
在这里插入图片描述
在这里插入图片描述
注意事项
在这里插入图片描述

多态性和virtual

在这里插入图片描述
在这里插入图片描述

C++ Virtual 完美诠释

#include<iostream>
using namespace std;
class Parent
{
public:
	virtual void show()
	{
		cout << "我是父类" << endl;
	}
};
class Child: public Parent   //如果没有写明继承方式,默认private
{
public:
	void show()
	{
		cout << "我是子类" << endl;
	}
};
void kshow(Parent *base)
{
	base->show();
}
int main()
{
	Child ch;
	//ch.show();//1.子
	其他都是输出父类
	指针
	//Parent *pa=nullptr;
	//pa->show();//2.父
	//pa = &ch;
	//pa->show();//3.子类赋值,仍输出父类。

	{
		Parent &p=ch;//4.引用
		p.show();

	}
	Parent pa;

	kshow(&ch);//5.指针传参
	kshow(&pa);




	/*ch = &pa;*///子类是特殊的父类,可以把子类赋值给父类,但不能颠倒


	//我想要传什么对象,就输出什么对象的show()
	//我发现了 就是加了virtual后 子类的赋值就能输出子类了 而不是一直都是父类  完成目标
	ch.show();

	return 0;
}

IO流

在这里插入图片描述
在这里插入图片描述

C常用英语单词

运算符与表达式: 1.constant 常量
 2.variable 变量 3.identify 标识符 4.keywords 关键字 5.sign 符号 6.operator 运算符
  7.statement 语句 8.syntax 语法 9.expression 表达式 10.initialition 初始化 11.numberformat 数据格式 12declaration 说明 13.type conversion 类型转换 14.define 、definition 定义 条件语句: 1.select 选择 2.expression 表达式 3.logicalexpression 逻辑表达式 4.Relational expression 关系表达式 5.priority 优先 6.operation 运算 7.structure 结构 循环语句: 1.circle 循环 2.condition 条件 3.variant 变量 4.process 过程 5.priority 优先 6.operation 运算 数组: 1.array 数组 2.reference 引用 3.element 元素 4.address 地址 5.sort 排序 6.character 字符 7.string 字符串 8.application 应用 函数: 1.call 调用 2.returnvalue 返回值 3.function 函数 4.declare 声明
5.`parameter 参数 6.static 静态的 7.extern 外部的 指针: 1.pointer 指针 2.argument 参数 3.array 数组 4.declaration 声明 5.represent 表示 6.manipulate 处理 结构体、共用体、链表: 1structure 结构 2member 成员 3tag 标记 4function 函数 5enumerate 枚举 6union 联合(共用体) 7create 创建 8insert 插入 9delete 删除 10modify 修改 文件: 1、file 文件 2、open 打开 3、close 关闭 4、read 读 5、write 写 6、error 错误
序号 主要章节 常用英汉对照词汇 备注 1 运算符与表达式 ( operatorandexpression ) 汉语 英语 常量 constant 变量 variable 标识符 identify 关键字 keywords 符号 sign 运算符 operator 语句 statement 语法 syntax 表达式 Expression 初始化 Initialization 数据格式 numberformat 说明 Declaration
类型转换 typeconversion 定义 Define 、 definition 2 条件语句 ( condition statement) 选择 select 表达式 expression 逻辑表达式 logicalexpression 关系表达式 Relationalexpression 优先 priority 运算 operation 结构 structure 3 循环语句 (circlestatement) 循环 circle 条件 condition 变量 variant 过程 process 优先 priority 运算 operation 4 函数 (function) 调用 call 返回值 returnvalue 函数 function 声明 declare 参数 parameter 静态的 static 外部的 extern 5 数组和指针 (arrayand pointer) 数组 array 引用 reference 元素 element 地址 address 排序 sort 字符 character 字符串 string 应用 application 指针 pointer 参数 argument 数组 array 声明 declaration 表示 represent 处理 manipulate 6 结构体、 共用体
(structures 、 union ) 结构 structure 成员 member 标记 tag 函数 function 枚举 enumerate 联合 ( 共用体 ) union 创建 create 插入 insert 删除 delete 修改 modify 7 文件 ( file) 文件 file 打开 open 关闭 close 读 read 写 write 错误 error
ProgramDesign 程序设计 writingprogram 编写程序 standardizevt.使标准化 codingtheprogram 编程 simplifyvt.单一化,简单化 programming 程序 revisionn.校订,修正 programmern.程序员 occupyvt.占领,住进 logicn.逻辑,逻辑学 BASIC 初学者通用符号指令代码 machinecode 机器代码 teachinglanguage 教学语言 debugn.DOS 命令,调试 simplicityn.单纯,简朴 compactnessa.紧凑的,紧密的 timesharingsystem 分时系统 descriptionn.描述,说明 interactivelanguage 交互式语言 breakn.中断 manufacturern.制造业者 structurechart 结构图 dialectn.方言,语调 theprogramflow 程序流 expensen.费用,代价 managermodule 管理模块
uniformityn.同样,划一 wordermodule 工作模块 archaica.己废的,古老的 mainmodule 主模块 sufficienta.充分的,足够的 submodule 子模块 dataprocessing 数据处理 modifyv.修正,修改 businessapplication 商业应用 outlinen.轮廓,概要 scientificapplication 科学应用 compose 分解 lexicala.字典的,词汇的 code 代码 non-programmer n.非编程人员 nodevt 改为密码 notationn.记号法,表示法,注释 pseudocoden.伪代码 verbosityn.唠叨,冗长 commasn.逗点逗号 recordn.记录 documentation 文档 subrecordn.子记录 flowchart/flow 程表/流程 datadivision 数据部 visuala.视觉的 proceduredivision 过程部 representvt.表现,表示,代表 comprisevt.包含 构成 structuredtechniques 结构化技术 operatorn.运算符,算子 straightforwarda.笔直的,率直的 commercial package 商业软件包 subroutinen.子程序 generatorn.产生器,生产者 drivermodule 驱动模块 mathematiciann.专家 linebyline 逐行 operatorn.作符 translatevt.翻译,解释 forerunnern.先驱 modular 摸块化 ancestorn.祖宗 cumbersomea.讨厌的,麻烦的
teachingprogramming 编程教学 lengthya.冗长的,漫长的 altervi./vt.改变 flawn.缺点裂纹 devclopvt.发达 separatea.各别的 recompile v.编译 assistn.帮助 cyclen.循环 techniciann.技师 removevt.移动,除去 straightline 直线 categoryn.种类,类项 rectanglen.长方形,矩形 P-codep 代码 virtrallyad.事实上 symology n.象征学象征的使用 registern.寄存器 tosummaries 总之,总而言之 byconvention 按照惯例 cypticn.含义模糊的,隐藏的 diamond-shapeda,菱形的 bracketn.括号 decisionn 判断 obviate 除去,排除 terminaln.a 终端机,终端的 keywordn.关键字 cardreader 阅读器 underlinevt.下划线 translatorprogram 译程序 monadica.monad(单位)的 Programming 程序设计 dec/binaryn.二进制 sourcelanguage 源语 shift 变化,转移,移位 machinelanguage 机器 overflown.溢出 machineinstruction 机器指令 arithmeticn.算术,算法 computerlanguage 计算机语 compositesymbol 复合型符号. assemblylanguage 汇编语 assignmentn.赋值 floatingpointnumber 浮点数
proliferationn.增服 high-levellanguage 高级语 pointern.指针 naturallanguage 自然语言 arrayn.数组矩阵, sourcetext 源文本 subscriptn.下标 intermediatelanguage 中间语言 typeconversion 类型转换 softwaredevelopment 软件开发 addressarithmetic 地址运算 mapvt.映射,计划 denotevt.指示,表示 maintenancecost 维护费用 subprogramn.子程序 legibilityn.易读性,易识别 separatecompilation 分离式编泽 amendvt.修正,改善 alphabetica.照字母次序的 consumern.消费者 digitn.数字位数 enormousa.巨大的,庞大的 numericexpression 数值表达式 reliabilityn.可信赖性,可信度 tapn.轻打,轻敲,选择 safetyn.安全,安全设备 printzone 打印区 propertyn.财产,所有权 columnn.列 correctnessn.正确, functionalityn.机能 semicolonn.分号 portablea.叮携带的,可搬运的 surveyn.概观. altogglen.肘节开关 taskn.作,任务 declarationn.宣告 说明 sourceprogram 源程序 mufti-dimensionarray 多维数组 objectprogram 目标程序

在这里插入图片描述

#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
	普通输出 cout
	//cout << "成毅" << endl;
	可以方便区别是干嘛
	//if (1)
	//{
	//	cerr << "报错" << endl;
	//}
	//clog << "璇玑追夫成功" << endl;



	//我们在C语言中有printf的格式输出,那么在c++中有控制格式输出的方式吗?
	//流成员的方式控制格式
	cout.width(10);        //设置字符宽度 只对挨着的有效
	//setf f是flag 标志
	cout.setf(ios::left);  //设置对齐格式
	cout.fill('*');		   //设置填充,默认是空白
	cout << "我爱你们" << endl;//一个汉字占两个字节

	cout.width(10);
	cout << 123 << endl;
	cout.width(10);
	cout << 520 << endl;

	//cout.setf(ios::scientific);//以科学计数法显示小数
	cout.setf(ios::fixed);//保留小数点后面几位
	cout.precision(2);//如果加上面 保留小数点后面几位   不加 保留有效位数几位
	cout << 3.1415 << endl;

	//以十进制,八进制,十六进制输出输出整数 dec oct hex
	int c = 13;
	cout << dec << c << endl;
	cout << oct << c << endl;
	cout.setf(ios::uppercase);//让输出中d-->D 以大写的方式显示十六进制中的字母
	cout << hex << c<< endl;


	//#include<iomanip> 这个库也就做了一点改变,稍稍方便了一点点
	cout << setiosflags(ios::scientific)  << setprecision(3) << 3.1415926 << endl;

	//bool类型
	cout <<  boolalpha<<  true << endl;//只有加了boolalpha会使输出时不再是1,而是true false 同样
	return 0;
}

标准输入流

在这里插入图片描述

文件IO

在这里插入图片描述

#include<iostream>
#include<fstream>
#include<string>//2013 需要加string 2019可不加
using namespace std;
//文件类
struct Girl
{
	int age;
	string name;
};
int main()
{
	fstream file("bin.txt", ios::in | ios::out | ios::binary | ios::trunc);
	if (!file)
	{
		cerr << "文件打开失败" << endl;

	}
	Girl myGirl[3] = { 12, "褚璇玑", 32, "褚玲珑", 23, "紫狐" };
	file.write((char*)myGirl, sizeof(myGirl));

	file.seekg(2*sizeof(Girl) ,ios::beg);//根据实际类型来偏移 所以前面的偏移量只能是sizeof(Girl)的倍数,其他会出现错误,全乱了

	Girl temp;
	file.read((char*)&temp, sizeof(temp));//这里也是一个重点
	cout << temp.age << " " << temp.name << endl;
	file.close();

	return 0;
}

异常处理

在这里插入图片描述
在这里插入图片描述

#include<iostream>
using namespace std;
//异常处理
//被零处理案例
int Div(int a, int b)
{
	if (b == 0)
	{
		throw "737373";
		cout << "被0整除" << endl;
	}
	return a;
}
//异常是跨函数的
//他会匹配捕捉类型,并且严格按照参数匹配,不会发生类型转换
int main()
{
	try
	{
		Div(1, 0);
	}
	catch (int a)
	{
		cerr << "被零整除" << a << endl;
		abort();//也可以自己中断
		throw;//也可以不处理,往外抛,没有人接,就会出现自动中断
	}
	catch (char a)
	{
		cerr << "被零整除" << a << endl;
	}
	//从上往下逐级匹配,匹配不到就执行。。。
	catch (...)
	{
		cerr << "被零整除"  << endl;
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述

问题

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

小项目 数组类 成员调用

#include<iostream>
#include<iomanip>
using namespace std;
class my
{
public:
	my()
	{
		Array = NULL;
		curSize = 0;
		capcity = 0;

	}
	my(int size)
	{	
		curSize = 0;
		capcity = size;
		Array = new int[capcity];
	}
	~my()
	{
		delete Array;
	}
	//插入
	void push_back(int num)
	{
		try
		{
			if (curSize == capcity)
			{
				throw curSize;
				
			}
		}
		catch (int size)
		{
			cerr << "数组超载" << endl;
		}
		curSize++;
		Array[curSize] = num;
	}
	//访问
	int &operator[] (int index)
	{
		if (index < 0 || index >= curSize)
		{
			cerr << "下标超界" << endl;
		}
		return Array[index];
	}
	void showData()
	{
		for (int i = 0; i < 10; i++)
		{
			cout << setw(6) << Array[i];
		}
	}
	//两个数组之间赋值
	void give(int *Arr)
	{
		for (int i = 0; i < capcity; i++)
		{
			Array[i] = Arr[i];
		}

	}
	//拷贝构造
	my(int *Arr)
	{
		for (int i = 0; i < capcity; i++)
		{
			Array[i] = Arr[i];
		}
	}
	//数组的所有成员乘以一个数
	int * Muti(int muti)
	{
		for (int i = 0; i < capcity; i++)
		{
			Array[i] = muti*Array[i];
		}
		return Array;
	}
private:
	int *Array;//数组指针
	int curSize;//数组当前大小
	int capcity;//数组最大容量
};
int main()
{
	my arr(10);
	for (int i = 0; i < 10; i++)
	{
		arr.push_back(i * 3);
	}
	arr.showData();

	arr.Muti(9);
	arr.showData();


	return 0;
}

小问题 内存窗口终于打开了

在这里插入图片描述
终于弄完了IO 这几天感觉学习状态明显下降,哎,今天9月8日,也是要离开家返校的日子了,说实话有点害怕,但只有在外面自己克服困难,才能成长。加油,希望你在新的学期,能够坚持越来越多的好习惯,让每一天都是好的东西的积累,还有希望能够吸取前面的经验,让自己的生活越来越幸福,越来越好,也希望你对成毅不是三分钟热度,他真的是一个很优秀的演员,他的生活态度,正是我心之所向,而且感觉他的处事态度和价值观也是我本身的类型。加油,毅往无前。
最后,记住一点要早睡早起,该花的钱不能省,尤其是早饭和中午饭。
记住买床帘,书架,坐垫,自行车,10点左右就睡觉哦,最迟十点半。
记住一定要预习,真的,那个知乎上的三步,其实只要你做到了,就可以用1/3的精力把学业搞好,其他的精力就可以花在你喜欢的事情上了。
这套课程一定要及时追上,加油。9月8日的我对你说,总的来说,在家这大半年,你做的还是很棒的。就像去跳广场舞一样,只要你自己下定决心,觉得这是一件好的事情就去做啊,不要问你的室友,到最后,不还是令别人刮目行看吗,他们都在夸你,战胜所谓的恐惧,你就向前迈进了一大步。

加油 加油 加油啊

模板

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>
using namespace std;
//实现两个数比较大小,并返回较大的数 int,char,float
template <typename T>//定义模板,告诉编译器,我要开始泛型编程了 除了typename 还可以用class
T Max(T a, T b)
{
	return a > b ? a : b;
}
int main()
{
	//隐式调用
	cout << Max(1, 2) << endl;
	cout << Max('A', 'B')<<endl;
	cout << Max(3.2, 8.3);
	//显示调用  函数名的后面加上 <类型参数列表>
	cout << Max<int>(3.13, 4.13);



	return 0;
}

为啥 j=0的时候越界
在这里插入图片描述
在这里插入图片描述
上面调用模板,下面使用普通函数
硬要调用模板
Max(‘a’,6); char可以隐形转换为整形

#include<iostream>
using namespace std;
int showMax(int a,int b)
{
	return a > b ? a : b;
}
template <typename T>
T showMax(T a, T b)
{
	return a > b ? a : b;
}
void show(int a,int b)
{
	cout << a << " " << b << endl;
}
template <typename T>
void show(T a, T b)
{
	cout << a << " " << b << endl;
}
template <typename T>
void show(T a, T b,T c)
{
	cout << a << " " << b << " "<<c<< endl;
}
int main()
{

	cout<<showMax(2, 4)<<endl;//当模板函数和普通函数都符合调用时,优先考虑普通函数
	showMax<>(2, 4);//若显示使用模板函数,则加<> 类型列表
	show(1, 2);
	show(1, 2, 3);//重载
	show('a', 2);//调用普通函数,可以产生隐式类型转换  模板函数不支持隐式转换


	return 0;
}

在这里插入图片描述
模板都是两次编译的机制
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

当缺少默认构造函数时,有三种办法
1.girl()
{

}
2.直接初始化

3.参数列表初始化
在这里插入图片描述

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

template <typename T>
class Ma
{
public:
	Ma(T b)
	{
		a = b;
	}
	void print()
	{
		cout << a << endl;
	}
	~Ma()
	{

	}
private:
	T a;
};

class Girl
{
public:
	Girl()
	{

	}
	Girl(const char* str, int ag) :age(ag)
	{
		strcpy(name, str);
		
	}
	//拷贝构造
	Girl(Girl & other)
	{
		strcpy(this->name, other.name);
		//this->name = other.name;//错误,字符串不能这样赋值
		this->age = other.age;
	}
	//重载
	friend ostream& operator<<(ostream& out,Girl& other)
	{
		out << other.age << " " << other.name << endl;
		return out;

	}
private:
	char name[20];
	int age;
};
int main()
{

	Ma<int> maye(7);
	maye.print();

	Ma<char *> cheng("5201314");//所以这个时候需要类模板
	cheng.print();

	string zc("hshah");//字符串
	Ma<string> str(zc);
	str.print();


	Girl g1("拿出点诚意爱成毅",19);
	Ma<Girl> sg(g1);
	sg.print();

	return 0;
}
#include<iostream>
using namespace std;
template <class T>
class TEST
{
public:
	TEST(T t)
	{
		this->t = t;
	}
	void show()
	{
		cout << t << endl;
	}
protected:
	T t;
};
//类模板派生普通类
class A :public TEST<int> //继承了模板类之后实例化
{
public:
	A(int a, int t) :TEST(t)
	{
		this->a = a;
		this->t = t;
	}
	void show()
	{
		cout << t<<" "<<a << endl;
	}
private:
	int a;

};
//类模板派生类模板
template <class T>
class B:public TEST<T>
{
public:
public:
	B(int a, int t) :TEST(t)
	{
		this->a = a;
		this->t = t;
	}
	void show()
	{
		cout << t << " " << TEST::t<< this->t<< a << endl;
	}
private:
	int a;

};

int main()
{
	TEST<int> t(3);
	t.show();

	A 司凤(12, 34);//这里不用加<> 已实例化
	司凤.show();

	B<int> 璇玑(4, 5);
	璇玑.show();

	return 0;
}

类的相加重载

#include<iostream>
using namespace std;
template <typename T>
class Complex
{public:
	Complex(T a, T b) :a(a), b(b){}
	//c1+c2
	Complex operator+(Complex& c)//重载+
	{
		Complex temp(this->a + c.a, this->b + c.b);
		return temp;
	}
	friend ostream& operator<<(ostream& out, Complex& c)
	{
		out << c.a << "+" <<c.b << endl; 
			return out;
	}
	void show()
	{
		cout << *this << endl;
	}
private:
	T a;
	T b;
};
int main()
{
	Complex<int> 爱你(520, 1314),cp(1,2);
	爱你.show();
	cout << 爱你 << endl;

	Complex<int> cp1 = 爱你 + cp;
	cout << cp1 << endl;
	cp1.show();
	return 0;
}

在这里插入图片描述
在这里插入图片描述

#include<iostream>
using namespace std;
int main()
{
	int n = 10;
	//int n1=static_cast<void>(n); void类型不能赋值给其他
	double cheng = static_cast<double>(n);

	//把整形指针转换为字符型指针
	int *p = &n;
	//char *pc = static_cast<char*>(p); F
	//static_cast 能转换普通数据类型,但不能转换指针类型和引用类型·。

	char* pc = reinterpret_cast<char*>(p);//这个只能用来转换指针
	//reinterpret_cast<double>(n); F

	const int ease = 29;
	//ease = 77;不能改、
	//int ps = const_cast<int>ease; //里面必须是指针或引用

	/*const char* 成毅 = "我爱你";*/
	const char 成毅[20] = "love";//在常量区没法修改 他声明为常量,其实内存仍然在栈区
	char* ps = const_cast<char*>(成毅);
	ps[0] = 'g';//注意字符单引号
	cout << ps << endl;
	return 0;
}

在这里插入图片描述

#include<iostream>
using namespace std;
class Animal
{
public:virtual void cry() /*= 0;*/
{
		   cout << "哭" << endl;
}
private:
};
class Dog:public Animal
{
public:
	virtual void cry()
	{
		cout << "汪汪" << endl;
	}

	   void homeSee()
	   {
		   cout << "看家" << endl;
	   }
};
class Cat:public Animal
{
public:virtual void cry()
{
		   cout << "喵喵" << endl;
}
	   void homeSee()
	   {
		   cout << "撸猫" << endl;
	   }
};
void show(Animal *base)//指针,要使用& 地址呗
{
	base->cry();
	//我们不知道传进来的是什么 dog 或cat
	//dynamic_cast可以把父类对象转换为子类对象 ,如果转换失败,则指针为空
	//检测是猫是狗
	Cat* pc = dynamic_cast<Cat*>(base);//子类就是特殊的父类
	if (pc)
	{
		cout << "猫抓老鼠" << endl;
		 pc->homeSee();//可以自己调用内部成员
	}
	Dog* p = dynamic_cast<Dog*>(base);
	if (p)
	{
		cout << "狗看家" << endl;
	}
}
int main()
{
	Dog dog;
	dog.cry();

	Animal an;
	show(&an);

	Cat cat;
	show(&cat);
	show(&dog);

	while(1);

	return 0;
}

因为Animal只是一个抽象类,只能用指针定义

C++11 14 标准

15才能用的编译器
在这里插入图片描述
判断使用了C++了没有,使用了就把NULL定义为0;
那C语言是把NULL定义为void* 0
在这里插入图片描述
在这里插入图片描述

auto 和 decltype推导类型

#include<iostream>
using namespace std;
void show(int *p)
{
	cout << "我是指针" << endl;
	
}
//void show(int p)
//{
//	cout << "我是整数" << endl;
//}

int/*auto*/ add(int a, int b)//形参里面不能用auto,但是返回值类型可以,在19行
{
	return a + b;
}
int main()
{
	//int bin = 0b10010; 可以在15 17 版本中使用
	unsigned num = 283839;
	
	show(NULL);//在C++中NULL是整数0;
	show(0);

	show(nullptr);//我的意思是传进去一个空指针
	//-----------------------------------------------------------

	//auto自动推导类型,只要右边有值,函数也可
	auto temp = 2;

	auto pfun = show;
	pfun(nullptr);

	//------------------------------------------------------------
	int nu = 2;
	decltype(nu) value = 20;//decltype 把nu的类型取出来了, 
	cout << value << endl;

	return 0;
}

后置返回类型

decltype 会根据你传进来的东西推导类型

auto add(int a, int b)->int   //尾随返回类型      //形参里面不能用auto,但是返回值类型可以,在19行
{
	return a + b;
}
template <typename T,typename U>
auto add(T a, U b)->decltype(a+b)//decltype的作用是根据值推导类型
{
	return a + b;
}

int main()
{
	
	
	cout << add(4, 5) << endl;
	cout << add('a', 4.5)<<endl;//去掉了整数 97+4 decltype(T+U)

	return 0;
}

别名

目前这个 我也不知道有啥用
在这里插入图片描述

lambda 匿名函数

在这里插入图片描述
在这里插入图片描述

#include<iostream>
using namespace std;
int main()
{
	//求相加的匿名函数
	//[](){}
	auto pfun =[](int a,int b)//pfun是一个指针 ,指向这个空间
	{
		return a + b;
	};
	//第一种调用方式
	cout << pfun(4, 5) << endl;
	//第二种调用方式
	cout<< [](int a, int b)	 {	return a + b;	}(6,4)<<endl;

	//当不需要传参时,可以去掉()
	[]{		cout << "我是最简单的lambda" << endl; }();//匿名函数要加分号,调用加()

	//[说明符]()mutable/throw{}
	/*
	=  按值导入外部变量 在内部捕获之后,相当于const修饰
	&  按引用导入外部变量
	this  按this指针导入外部变量,用在类里面
	*/
	int num = 333;

	[=]()mutable{ num = 123;		cout << num << endl; }();
	cout << num << endl;//mutable 只是临时改变

	[&](){ num = 111;		cout << num << endl; }();
	cout << num << endl;//mutable 只是临时改变

	int a1 = 2,= 2,= 2;
	[&](){= 3;		cout <<<< endl; }(); //传进来谁就能修改谁



	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<regex>
using namespace std;
//正则表达式
int main()
{
	cout<<regex_search("mayehdhja", regex("maye[\\w]*ja$"));// 在regex()中,^ 开头  $结尾(后置)
	string str = "123.678.9.8";
	/*regex re("[a-b]{2}");*///regex re(".") 这个是匹配一个字符的
	regex re("[0-9]{3}.[0-9]{3}.[0-9]{1,3}.[0-9]{1,3}");// \. 转义字符
	//[maye] 匹配里面的任意一个字符
	//[0-9A-Z_] 从左到右匹配 匹配在这个范围内的一个字符
	//^  [^%$#@][0-9A-Z_]前面加上^后,其后面出现的一坨都不能出现 ^必须写在中括号的开头
	//? 跟在前面的单元出现0 或1次
	//+  跟在前面的单元出现1 或多次
	//*  跟在前面的单元出现0 或多次
	//{N} 跟在前面的单元精准匹配N次
	//
	
	/*bool isok = regex_match(str, re);
	if (isok)
	{
		cout << "匹配成功" << endl;
	}
	else
	{
		cout << "匹配失败" << endl;
	}*/
	bool isok = regex_match("12333@qq.com", regex("[\\w]*@[\\w]*.com"));
	if (isok)
	{
		cout << "匹配成功" << endl;
	}
	else
	{
		cout << "匹配失败" << endl;
	}
	return 0;

}

STL模板库

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
说简单一点,就是序列式容器:不会排序
关联式容器:会排序元素

STL 之string容器的一些指令

#include<iostream>
#include<string>
using namespace std;
void obj1()
{

	string str;
	string str1 = "fheng yi";//string str1("成毅 加油 我么都在")
	string str2 = str1;
	string str3(10, 'c');
	cout << str3 << endl;

	//中断异常不同,
	cout << str2[0] << endl;//当访问最后一个元素的下一个位置时,不会直接报错,但是继续访问时,不会抛出异常
	cout << str2.at(0) << endl;


	//str2[str2.size() + 1 访问最后一个元素的下一个异常
	//str2.size() 访问最后一个元素异常

	//检验
	try
	{
		/*cout << str2[str2.size() + 1] << endl;*///当访问最后一个元素的下一个位置时,不会直接报错,但是继续访问时,不会抛出异常
	}
	catch (...)
	{
		cout << "我发生了异常" << endl;
	}

	try
	{
		cout << str2.at(str2.size());
	}
	catch (...)
	{
		cout << "at 发生了异常" << endl;
	}

}
//string .copy
void obj2()
{
	string cheng = "cheng";
	char name[10] = "";
	cheng.copy(name, 2, 2);//第三个位置表示从cheng【2】开始的两个字符 进行拷贝
	cout << name << endl;

	cout << cheng.size() << " " << cheng.length() << " " << cheng.empty() << endl;//length()和size()是一样的
	
}
void obj3()
{
	string ch = "cc晨";
	ch = "成毅";
	ch.assign ("ch;");
	string zc = "chengyi woaini";
	ch.assign(zc.begin(), zc.begin() + 3);
	cout << ch << endl;
	//迭代器遍历
	for (string::iterator it = zc.begin(); it != zc.end(); it++)
	{
		cout << *it ;
	}
	cout << endl;
	for (char t : zc)//需要了解
	{
		cout << t;
	}
	//简单的连接
	string s = "lov";
	s += "e";//这两种方式都可以连接
	s.append(" 成毅");
	cout << s << endl;
	//剪切
	string chh = "chengyi ainiaini";
	/*cout << chh.substr(0, 5);*/
	//查找
	cout << chh.rfind('e') << endl;
	//替换
	chh.replace(0, 6, "you");//从0这个位置开始的6个位置将被替代
	cout << chh<<endl;
	//任意位置插入
	chh.insert(3, "huahua");
	cout << chh << endl;
	chh.erase(2, 3);//从2这个位置开始删除3个
	cout << chh << endl;
}
int main()
{
	obj3();





	return 0;
}

vector容器

vector 容器在尾部删减和添加都非常的方便,但是在头部和中部就不
#include<iostream>
#include<vector>
using namespace std;

	

void print(vector<int> vec)
{
vector<int>::iterator it = vec.begin();
for (it; it != vec.end(); it++)
{
	cout << *it ;
}
cout << endl;

}
int main()
{
	//初始化
	vector<int> vec(5, 6);
	vector<int> vec1(vec);
	vector<int> vec2(vec1.begin(), vec1.end());
	vector<int> vec3;
	vec3.assign({ 1, 2, 3, 4, 5, 5 });//赋值
	vec3.swap(vec);//交换

	//不能这样输出
	/*cout << vec << endl;
	cout << vec3 << endl;*/

	//容器的名字::迭代器定义
	vector<int>::iterator it = vec.begin();
	for (it; it != vec.end(); it++)
	{
		cout << *it ;
	}
	cout << endl;
	//限制容器长度
	vec.resize(3);
	print(vec);
	//多出来 的默认0来补位
	/*vec.resize(10);*/
	print(vec);
	//可以调整默认补位数字
	vec.resize(10,3);
	print(vec);

	//添加和修改
	vec.push_back(999);//尾部添加
	print(vec);
	//下标修改 两种 
	vec[3] = 123;
	vec.at(0) = 111;
	print(vec);

	vec.pop_back();//尾部删除,无参数
	print(vec);
	return 0;
}

deque

跟那个vector很像 一大部分 担忧一些区别 他在头部和尾部都很方便
删除添加 中部不太方便
#include<iostream>
#include<deque>
using namespace std;
void print(deque<int> q)
{
	deque<int>::iterator it = q.begin();
	for (it; it != q.end(); it++)
	{
		cout << *it;
	}
	cout << endl;
}
class vector
{public:
	vector()
	{

	}
	~vector()
	{}

};
int main()
{
	deque<int> deq(4,6);
	deque<int> dq1(deq);
	deque<int> dq2(dq1.begin(), dq1.end());
	for (int i = 0; i < 10; i++)
	{
		dq2.push_back(i);//尾部添加
	}
	print(dq2);
	dq2[0];
	dq2.at(0);
	//删除头部和尾部
	dq2.pop_back();
	dq2.pop_front();
	print(dq2);
	

	//输出第一个 和最后一个
	cout<<dq2.front()<<endl;
	cout << dq2.back() << endl;

	

	dq2.clear();//清空所有
	print(dq2);
	return 0;
}

注意:iterator 是类中类,可以自己构造迭代器 ,这里略 详细请看STL左后一部分

list容器

it+5(err)是连续的内存才能这样 ,list只支持一个一个的·加
不支持随机存取(at)
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<list>
#include<vector>
#include<algorithm>
using namespace std;
void print(list<int> is)
{
	list<int>::iterator it;
	for (it=is.begin(); it != is.end(); it++)
	{
		cout << *it<<" ";
	}
	cout << endl;
}
int main()
{
	list<int> s1;
	for (int i = 0; i < 10; i++)
	{
		s1.push_back(rand()%50);
	}
	print(s1);
	//正向迭代器
	//反向迭代器
	list<int>::reverse_iterator rit = s1.rbegin();
	for (rit; rit != s1.crend(); rit++)
	{
		*rit += 2;
		cout << *rit << " ";
	}
	cout << endl;
	
	//常量迭代器
	list<int>::const_iterator cit = s1.cbegin();
	for (cit; cit != s1.cend(); cit++)
	{
		//只能遍历,不能修改
		cout << *cit << " ";
	}
	cout << endl;

	//这个排序真好用
	//只有我们的列表能排序 ,因为他不支持随机访问,
	//且length 只有string有。
	s1.sort();
	s1.remove(34);//消除匹配的元素
	print(s1);
	//--------------------------------------------------
	//这样也是可以成功排序的
	vector<int> vec = { 1, 4, 2, 3, 4, 2, 3, 4, 5, 56, 3, 44 };
	sort(vec.begin(),vec.end());//在algorithm里面
	for (auto t : vec)
	{
		cout << t << " ";
	}
	return 0;
}

queue容器

//栈是没有迭代器的,你只能的访问顶部
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
int main()
{
	queue<int> qu;
	for (int i = 0; i < 10; i++)
	{
		qu.push(rand() % 25);
		
	}
	while (!qu.empty())
	{
		cout << qu.front() << " ";
		qu.pop();
	}
	cout << endl;
	cout << qu.size() << endl;

	return 0;
}
int main000()
{
	//同样是一个模板类,需要指定类型
	stack<int> sk;
	for (int i = 0; i < 10; i++)
	{
		sk.push(rand()%15);//进栈

	}
	while (!sk.empty())
	{
		cout << sk.top() << " ";
		sk.pop();//无参数
	}
	cout << endl;
	cout << sk.size();


	return 0;
}

set容器

在这里插入图片描述

#include<iostream>
#include<set>

using namespace std;
void print(set<int> s)
{
	set<int>::iterator it;
	for (it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";

	}
	cout << endl;
}
void objset()
{
	set<int> s;
	for (int i = 0; i < 10; i++)
	{
		s.insert(rand() % 12);
		
	}
	print(s);
	cout << s.count(11) << endl;//count的返回值不是0就是1,因为他最多允许一个键出现一次

	//会出现bug 会遍历到末尾 *end出现错误 
	set<int>::iterator it = s.find(100);
	if (it != s.end())
	{
		cout << *it << endl;//find返回的是一个迭代器
	}
}
void objset2()
{
	set<int> a;
	a.insert(2);
	a.insert(3);
	a.insert(34);
	a.insert(22);
	a.insert(21);
	print(a);
	set<int>::iterator it = a.lower_bound(4);//大于等于他的最小值
	cout << *it;
	set<int>::iterator iit = a.upper_bound(4);//大于等于他的最小值
	cout << *iit;
	//set<int>::iterator iot = a.equal_bound(4);//大于等于他的最小值
	//cout << *iit;

	using T = set<int>::iterator;
	pair<T, T> pp = a.equal_range(8);
	cout << *pp.first << " " << *pp.second;

}
//mutiset 和set的唯一区别就是键不唯一
void objset3()
{
	multiset<int> a;
	a.insert(2);
	a.insert(3);
	a.insert(34);
	a.insert(22);
	a.insert(21);
	a.insert(2);
	a.insert(3);
	a.insert(34);
	a.insert(22);
	a.insert(21);
	multiset<int>::iterator it;
	for (it = a.begin(); it != a.end(); it++)
	{
		cout << *it << " ";

	}
	cout << endl;
}
int main()
{
	//objset();//自动排序
	//objset2();
	objset3();

	return 0;
}

pair

其实就是返回两个指针,当返回多于1个时,就要返回结构体。

函数指针

仿函数

写仿函数时,进本数据类型会自动排序,但是类中的成员排序就需要emmmm

#include<iostream>
#include<set>
using namespace std;
template<typename FUNC>
int arrNum(int *first, int *last, /*int (*isRight)(int)*/FUNC func)//这个函数指针不懂 可以看下面的连接
                                                     //应是这样的 isok是一个类的对象,就要传进来类模板
{
	int _count = 0;
	while (first != last)
	{
		
		if (func(*first))//bool operator()(int elem)重载的就是这里
		{
			_count++;
		}
		first++;
	}
	return _count;
}
bool isRight(int elem)
{
	return elem > 10;
}
struct isok
{
	isok(int num = 0) :num(num){};
	bool operator()(int elem)//仿函数实质就是在类中重载 多一个参数 我们该怎么样处理
	{
		return elem > num;
	}
private:
	int num;
};


struct Person
{
	Person(int id = 0, int age = 0) :id(id), age(age)
	{
	}
	~Person()
	{
	}
	void show() const
	{
		cout << id << " " << age << "-----";
	}
	int id;
	int age;
};
struct isOk
{
	bool operator()(Person p1, Person p2)
	{
		return p1.age > p2.age;
	}
};
void per()
{
	set<Person,isOk> sp;//<>里面第一个是类型,第二个是比较规则
	Person p1(2, 12), p2(23, 45), p3(22, 33);
	sp.insert(p1);
	sp.insert(p2);
	sp.insert(p3);
	
	set<Person,isOk> ::const_iterator it = sp.begin();
	for (it; it != sp.cend(); it++)
	{
		(*it).show();
	}
	


}

int main()
{
	//int arr[] = { 1, 3, 5, 5, 45, 56, 23, 12, 66 };
	//int len = sizeof(arr)/sizeof(arr[0]);
	//cout << len << endl;

	//cout<<arrNum(arr, arr + len, isok(10));//这里还是不懂 上面从函数指针改成类模板,就好了 why

	per();


	return 0;
}

<>
里面有两个
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

map容器

//map是标准的关联式容器,一个map是一个键值对序列  即(key,value)序列
#include<iostream>
#include<map>
#include<functional>//less 和 greater 的头文件
#include<string>
using namespace std;
void obj()
{   //key value
	//基本数据类型会有默认的比较规则来排序 就是less 从低到高
	map<int, int> m;
	//m.insert(1, 2);//虽然没有立即报错 但是不能直接写进去 而是要用pair
	//第一种方法
	m.insert(pair<int, int>(1, 2));
	//第二种
	m.insert(make_pair(2, 3));
	//第三种
	m.insert(map<int, int>::value_type(3, 4));

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

	cout << m[0] << endl;//不确定
	cout << m[1] << endl;
	m[0] = 20;//直接修改
	cout << m[0] << endl;
	m[12] = 23;//如果没有,会自动创建并赋值
	cout << m[12] << endl;
}
void obj2()
{//其他都很类似,查找的find 和count 值得讲一讲
	map<string, int, greater<>> sp;
	sp.insert(make_pair("成毅", 211314));
	sp.insert(make_pair("冲", 18));
	sp.insert(make_pair("mami", 20));

	map<string,int>::iterator it=sp.find("成毅");//如果没有查找到,就返回it.end() 所以应该检测是否为end
	if (it != sp.end())//这里不能用while 会重复循环
	{
		cout << it->first << " " << it->second << endl;
	}

	it = sp.begin();
	for (it; it != sp.end(); it++)
	{
		cout << it->first << " " << it->second << endl;
	}
}
int main()
{
	obj();
	obj2();
	while (1);
	return 0;
}

multimap 案例

/*

Multimap案例:
//1个key值可以对应多个value=分组
//公司有销售部sale(员工2名)、技术研发部 development(1人)、财务部Financial(2人)
//人员信息有:姓名,年龄,电话、工资等组成
/通过multimap进行信息的插入、保存、显示
//分部门显示员工信息

*/
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main()
{
	class Work
	{public:
		Work(string name, int age, string tel, int sla) :_name(name), age(age), _tel(tel), salary(sla)
		{
		}
		void show()
		{
			cout << _name << "\t" << age << "\t" << _tel << "\t" << salary << endl;//换行符是要带括号的
		}
	private:
		string _name;
		int age;
		string _tel;
		int salary;
	};

	Work w1("chn", 12, "0-2376726", 1234), w2("成毅", 30, "7_322866", 1234), w3("傅诗淇", 29, "2738-37827", 2232),
		w4("噢噢", 12, "82379721", 7878),w5("花花",13,"3-23239283",9999);
	multimap<string, Work> m;
	//不能直接写进去,要进去的是pair 类型
	m.insert(make_pair("sale", w1));
	m.insert(pair<string, Work>("sale", w2));
	m.insert(make_pair("development", w3));
	m.insert(make_pair("Financial", w4));
	m.insert(make_pair("Financial", w5));
	
	/*multimap<string, Work>::iterator*/ auto it = m.begin();
	string key;//为了不让第一个部门每次都出现
	for (it; it != m.end(); it++)
	{
		if (it->first != key)//为了不让第一个部门每次都出现
		{
			cout << it->first << endl;
			key = it->first;
		}
		 it->second.show() ;
		
	}

	return 0;
}

在这个vector 容器内 如果不使用聚合初始化,那么就要用push_back 一个一个的插入,
在这里插入图片描述

队列 先进先出 栈:先进后出 顺序固定 不能更改

STL容器共性机制

在这里插入图片描述
multi 是多的意思 二叉树的查找都特别快
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

STL部分算法

大概有100多个算法,详细请看C++手册

#include<iostream>
#include<algorithm>
#include<functional>
#include<vector>
#include<list>
using namespace std;
void print(vector<int> v)
{
	auto it = v.begin();
	for (it; it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
int show(int num)
{
	cout << num << " ";
	return num;
}
void find_sort()
{
	vector<int> m = { 1, 2, 7, 3, 2, 4, 4, 3, 5, 5 };
	print(m);
	sort(m.begin(),m.end(),greater<>());//默认从小到大, 而且只适用于三种容器
	print(m);
}
//将指定范围内的元素进行转换,并将结果存储在从result开始的范围中
void fun_transform()
{
	vector<int> v = { 1, 6, 4, 6, 5 };
	vector<int> vv(10);//没有大小就是没有内存,会报错
	vv.resize(v.size());//调整大小

	transform(v.begin(), v.end(), vv.begin(), show);
	print(v);
	print(vv);
}
void fun_find()
{
	vector<int> vec = { 1, 4, 3, 5, 6, 3 };
	vector<int>::iterator it = find(vec.begin(), vec.end(), 4);
	if (it != vec.end())
	{
		cout << *it << " ";
	}
}
int cmp(int i)
{
	return i > 2;
}
//find_if
void fun_find_if()//find_if 自定义比较标准 替换==
{
	vector<int> v = { 1, 4, 3, 5, 6 };
	auto it = find_if(v.begin() + 2, v.end(), cmp);
	cout << *it<<endl;
}
//adjacent_find
void fun_adjacent_find()//adjacent_find 查找两个连续的元素,并返回第一个元素的迭代器
{
	vector<int> v = { 1, 4, 3, 5,5, 6 };
	auto it = adjacent_find(v.begin() + 2, v.end());
	cout << *it<<" ";
	cout << *(it++) << endl;
}
//该函数专门用来对容器或普通数组中指定范围内的元素进行处理,把处理功能用函数封装。返回一 个函数对象

//for_each 和transform 不一样,因为前面只是进行操作,而后面会放到一个新的容器
void fun_for_each()
{
	vector<int> v = { 1, 4, 3, 5, 6 };
	for_each(v.begin(), v.end(), show);//回调函数 函数指针在内部
	cout << endl;
}
void fun_count()
{
	vector<int> v = { 1, 4, 3, 5, 6 ,12,2,2,2,2,2};
	cout << count(v.begin(), v.end(), 2) << endl;//查找一共有多少个对应元素
}
//copy返回的迭代器指向这一段末尾在新容器的位置 ,也就是最后一个元素的下一个
void fun_copy()
{
	vector<int> v = { 1, 2, 3, 45, 5, 5 };
	vector<int> vv(v.size()+2 );
	list<int> dog(v.size() + 2);//只有有拷贝功能,有迭代器,也可以拷贝到其他容器
	copy(v.begin(), v.end(), dog.begin());
	cout << *copy(v.begin(), v.end(), vv.begin()) <<  "这是copy返回值";
	for (int i : vv)
	{
		cout << i << " ";
	}
	for (int i : dog)
	{
		cout << i << " ";
	}
}

int main()
{
	

	
	find_sort();
	fun_transform();
	fun_find();
	fun_find_if();
	fun_adjacent_find();
	fun_for_each();
	fun_count();
	fun_copy();
	return 0;
}

我惊奇的发现 如果在标题上加上<key,value>这种后面就不显示

适配器

谓词
谓词是指普通函数或重载的operator()返回值是bool类型的函数对象(仿函数)。如果 operator接受一个参数,那么叫做一元谓词,如果接受两个参数,那么叫做二元谓词,谓词 可作为一个判断式 函数对象适配器
函数对象适配器是完成一些配接工作,这些配接包括绑定(bind),否定(negate),以及对一 般函数或成员函数的修饰,使其成为函数对象,重点掌握函数对象适配器(红色字体):
bind1st 将参数绑定为函数对象的第一个参数
bind2nd 将参数绑定为函数对象的第二个参数
not1 对一元函数对象取反
not2 对二元函数对象取反 ptr_fun 将普通函数修饰成函数对象

前四个重点掌握
mem_fun 修饰成员函数(容器里存的是对象)
mem_fun_ref 修饰成员函数(容器里存的是指针

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

//void show(int a,int num)
//{
//	cout << a+num << " ";//想传两个参数 下面for_each 就不行
//}
struct MyStruct:binary_function<int,int,void> //要继承二元仿函数的基类 两个变量的类型都是int 返回类型是void
{
	void operator()(int a, int num) const
	{
		cout <<a<<"+"<<num<<" "<< a + num << " "<<endl;//想传两个参数 使用仿函数 结构体内重载
	}

};
void print(vector<int> v)
{
	auto it = v.begin();
	for (it; it != v.end(); it++)
	{
		cout << *it << " ";
	}
}
void fun_bind2nd()
{
	vector<int> v = { 1, 3, 5, 6, 3, 5 };

	for_each(v.begin(), v.end(), bind1st(MyStruct(), 12));
}
struct CMP:unary_function<int,int> //not1 和 not2 继承的基类是unary_functoin  最后一个是返回类型,前面的是对应变量的类型
{
	//const //加在函数名后面 修饰的是this指向指向的对象不可修改
	int operator()(int a) const
	{
		return a > 5;//取反 a>5的反 是a<=5
	}
};

void fun_not()
{
	vector<int> v = { 5, 3, 5, 6, 3, 5 };

	cout<<*find_if(v.begin(), v.end(),not1(CMP()))<<endl;//要求CMP对应的重载仿函数加const 
}
int search(int num)
{
	return num > 5;
}
void fun_ptr()
{
	vector<int> v = { 5, 3, 5, 6, 3, 5 };

	cout << *find_if(v.begin(), v.end(), not1(ptr_fun(search)));//要求CMP对应的重载仿函数加const 
}
/*
//bind1st  将参数绑定为函数对象的第一个参数
//bind2nd  将参数绑定为函数对象的第二个参数 
//not1    对一元函数对象取反 
//not2    对二元函数对象取反

上述这些的括号内都是函数对象 所以可以

//ptr_fun   将普通函数修饰成函数对象
//mem_fun  修饰成员函数(容器里存的是对象)
//mem_fun_ref 修饰成员函数(容器里存的是指针)
*/
class Person
{
public:Person(int age, int id) :_id(id),_age(age){}
	   void show()
	   {
		   cout << "age:" << _age << "id: " << _id << " "<<endl;

	   }
private:
	int _id;
	int _age;
};
void fun_mem()
{//有ref的是装对象的,没有的是装对象指针的
	vector<Person> v = {Person(1,2),Person(3,5),Person(6,7) };
	for_each(v.begin(), v.end(), mem_fun_ref(&Person::show));//适配成员函数指针

	Person P1(1, 2), P2(3, 5), P3(6, 7);
	vector<Person*> vv = { &P1,&P2,&P3 };
	for_each(vv.begin(), vv.end(), mem_fun(&Person::show));
}
int main()
{
	
	
	fun_bind2nd();
	fun_not();
	fun_ptr();
	fun_mem();
	return 0;
}

当然也可以嵌套not2(bind2nd(Mycmp()))
在这里插入图片描述

声明和 定义只能保留一个地方的默认参数

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值