目录
1.list列表
list是双向的列表,高效的插入和删除,但是读取效率稍低。不支持下标操作,用迭代器来操作
#include <iostream>
#include <list> //写明头文件
using namespace std;
int main(){
list<string> lis; //创建空list列表
//尾部增加
lis.push_back("AA");
lis.push_back("BB");
lis.push_back("CC");
lis.push_back("DD"); //AA BB CC DD
//尾部删除
lis.pop_back(); //AA BB CC
//头部增删
lis.push_front("tom"); //tom AA BB CC
lis.pop_front(); //AA BB CC
//lis.erase(lis.begin()+2); //vector的方法不可用
//list列表迭代器不支持随机访问 list迭代器访问最后一个和前一个是可以的
lis.erase(++lis.begin()); //AA CC
lis.push_back("EE");
lis.push_back("FF"); //AA CC EE FF
//插入
list<string>::iterator it=lis.begin();
advance(it,2); //再往后移动2位
cout<<*it<<endl; //EE
lis.insert(it,"hello"); //AA CC hello EE FF
//删除最后的元素
lis.erase(--lis.end()); //AA CC hello EE
//lis.erase(lis.end()); 直接这样可能会全删除
for(string s:lis){
cout<<s<<" ";
}cout<<endl;
}
#include <iostream>
#include <list> //写明头文件
using namespace std;
int main()
{
list<string> lis;
lis.push_back("AA");
lis.push_back("BB");
lis.push_back("CC");
lis.push_back("DD"); //AA BB CC DD
list<string>::iterator it=lis.begin();
advance(it,1);
cout<<*it<<endl; //BB
//删除
it=lis.erase(it);
//删除之后会返回删除元素后面的位置的迭代器。但是需要迭代器变量重写来接收
cout<<"删除之后:"<<*it<<endl;
//lis.erase(it); 再cout<<*it<<endl; 出来的是乱码
//it=lis.erase(it); 再cout<<*it<<endl; 出来的是下一个字符串
//比如AA BB CC DD it是BB,it=lis.erase(it); 再cout<<*it<<endl; 出来的是CC
//结果是AA CC DD
for(string s:lis)
{
cout<<s<<" ";
}
}
list列表应用:选猴王
有n只猴围城一圈,从1开始报数,数到m的就离开。直到最后一只猴,这只猴就是猴王
#include <iostream>
#include <list> //写明头文件
using namespace std;
int main()
{
int n,m;
cin>>n>>m; //n 总数 查到m删除
list<int> monkeys;
for(int i=1;i<=n;i++) //5
{
monkeys.push_back(i);
}
list<int>::iterator it=monkeys.begin();
//当个数=1的时候停止 所以>1的时候循环
while(monkeys.size()>1){
for(int i=1;i<m;i++){ //m=3
it++;
//如果加到end()时证明已经到末尾了,转成开头的元素继续报数
if(it==monkeys.end()){
it=monkeys.begin();
}
}
it=monkeys.erase(it);
//删除之后如果到了end()位置 ,应转到开头元素位置
if(it==monkeys.end()){
it=monkeys.begin();
}
cout<<"准备删除的元素是:"<<*it<<endl;
for(int j:monkeys)
{
cout<<j<<" ";
}
cout<<endl;
}
cout<<"猴王编号:"<<monkeys.front()<<endl;
}
2.deque队列
API兼顾vector和list,性能在两者之间 ,和前面通用;
关联容器
元素之间位置并没有严格物理上的顺序关系,不能指明元素的位置。但内部会自动的排序;
常见的关联容器:map(键值对) mulitmap(多重键值对)
#include <iostream>
#include <map>
using namespace std;
int main(){
map<string,int>mp;
cout<<mp.empty()<<endl; //1空 0非空 判断是不是空的
mp["age"]=20; //键是age 值是20
//如果map中没有键,mp["age"]=20;相当于新增
cout<<mp["age"]<<endl; //20
mp["age"]=30;
cout<<mp["age"]<<endl; //30 //相当于更新操作
//map中的键是不允许重复的
if(mp.find("age")==mp.end()){
cout<<"没找到,不存在!"<<endl;
}else{
cout<<"找到,已经存在!"<<endl;
}
//插入操作 pair是个有键值对的模板
pair<string,int> pair1;
pair1.first="hello"; //键
pair1.second=70; //值
mp.insert(pair1);
mp.insert( pair<string,int> ("world",80));
cout<<mp["hello"]<<endl; //70
}
键---值
#include <iostream>
#include <map>
using namespace std;
int main(){
map<string,int> mp;
cout<<mp.empty()<<endl;
mp["age"]=20;
cout<<mp["age"]<<endl;
if(mp.find("age")==mp.end()){
cout<<"no"<<endl;
}else{
cout<<"yes"<<endl;
}
pair<string,int> pair1;
pair1.first="height";
pair1.second=150;
mp.insert(pair1);
cout<<mp["height"]<<endl;
mp.insert(pair<string,int>("weight",1000));
//mp.insert(pair<string,int>("height",1000)); //height键已存在 键相同 不允许插入成功
cout<<mp["weight"]<<endl;
}
3.迭代器
------>[遍历]
迭代器是个特殊的指针。通用的形式访问各种容器;iteratro 可读可写 const iterator 可读
通常使用迭代的方式遍历容器,效率比较高
#include <iostream>
#include <map>
#include <vector>
#include <list>
using namespace std;
int main(){
map<string,int> mp;
mp.insert(pair<string,int>("weight",1000));
mp.insert(pair<string,int>("height",1900));
mp.insert(pair<string,int>("age",20));
map<string,int>::iterator it;
for(it=mp.begin(); it!=mp.end() ; it++){
cout<<it->first<<" "<<it->second<<endl;
}
cout<<"----------------------------"<<endl;
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
vector<int>::const_iterator it2;
for(it2=v.begin();it2!=v.end();it2++){
cout<<*it2<<" ";
//++*it2; //只读迭代器 只允许读取
}cout<<endl;
cout<<"----------------------------"<<endl;
list<string> lis;
lis.push_back("Tom");
lis.push_back("Jerry");
lis.push_back("link&co");
lis.push_back("BMW");
list<string>::iterator it3;
for(it3=lis.begin();it3!=lis.end();it3++){
cout<<*it3<<endl;
}cout<<endl;
}
4.继承
(面向对象三大特征:封装 继承 多态)
定义:从已有的类的继承上,创建新的类,会拥有已有类的属性和方法,通常会再此继承上添加新的属性和方法,完成扩充
已存在的类 成为基类 或者 父类
新的类 成为派生类 或者 子类
#include <iostream>
#include <map>
#include <vector>
#include <list>
using namespace std;
class Father{
public:
string name = "wang";
void work(){
cout<<"share"<<endl;
}
void show(){
cout<<"name: "<<name<<endl;
}
};
class Son:public Father{
};
int main(){
Son s;
s.show();
s.work();
}
派生类可自己再定义一些属性
如果子类中给出了父类同名的函数,会把父类的同名函数隐藏起来
#include <iostream>
using namespace std;
class Father{
public:
string first_name="王";
void work(){
cout<<"我是一名理发师"<<endl;
}
void show(){
cout<<"姓氏:"<<first_name<<endl;
}
};
class Son:public Father{
public:
int age=20;
void work(){
cout<<"我是一名老师"<<endl;
}
void play_game(){
cout<<"玩游戏"<<endl;
}
};
int main(){
Son s;
s.work();
s.play_game();
cout<<s.first_name<<" "<<s.age<<endl;
}
调用父类隐藏的函数需要 父类::函数名 的方式访问
#include <iostream>
#include <map> //写明头文件
#include <vector>
#include <list>
using namespace std;
class Father{
public:
string first_name="王";
void work(){
cout<<"我是一名理发师"<<endl;
}
void show(){
cout<<"姓氏:"<<first_name<<endl;
}
};
class Son:public Father{
public:
int age=20;
void work(){
cout<<"我是一名老师"<<endl;
}
void show(){
Father::show();
cout<<"年龄:"<<age<<endl;
}
};
int main()
{
Son s;
s.work(); //隐藏了父类的同名函数,子类直接调用只会打印子类中的函数
s.Father::work(); //父类::
s.show();
}
继承的注意事项:
父类的构造函数不会继承下来
子类一定要最直接或间接调用父类的构造函数,来完成父类继承过来数据的初始化,如果子类不写明如何调用父类的构造函数,这时会调用父类无参的构造函数。如果父类没有无参的构造函数,这是会报错
如下:会报错的!
#include <iostream>
using namespace std;
class Father{
private:
string first_name;
public:
Father(string s)
{
first_name=s;
}
void show(){
cout<<"姓氏:"<<first_name<<endl;
}
};
class Son:public Father{
};
int main()
{
Son s;
}
E:\qtfile\helloworld\main.cpp:21: error: use of deleted function 'Son::Son()'
Son s;
^
4.1继承中的构造函数
透传函数
直接调用父类的构造函数,称为透传构造
#include <iostream>
using namespace std;
class Father{
private:
string first_name;
int age;
public:
Father(string s){
first_name=s;
}
Father(string first_name,int age){
this->first_name=first_name;
this->age=age;
}
void getFirstname(){
cout<<"姓氏:"<<first_name<<endl;
}
void show(){
cout<<"姓氏:"<<first_name<<"年龄:"<<age<<endl;
}
};
class Son:public Father{
private:
int height; //子类新增的
public:
Son(string name,int age):Father(name,age){}
Son(string name, int age,int height):Father(name,age){
this->height=height; //子类新增的属性,自己完成初始化
}
void son_show(){
Father::show();
cout<<"身高:"<<height<<endl;
}
};
int main(){
Son s("小红",20);
s.show();
Son s2("小米",20,167);
s2.son_show();
}
委托构造
间接的调用父类的构造函数,子类的构造函数调用子类另一个构造函数,另一个构造函数调用了父类的构造函数,相当于间接调用父类的构造函数
#include <iostream>
using namespace std;
class Father{
private:
string first_name;
int age;
public:
Father(string s){
first_name=s;
}
Father(string first_name,int age){
this->first_name=first_name;
this->age=age;
}
void getFirstname(){
cout<<"姓氏:"<<first_name<<endl;
}
void show(){
cout<<"姓氏:"<<first_name<<"年龄:"<<age<<endl;
}
};
class Son:public Father{
private:
int height; //子类新增的
public:
Son(string name):Son(name,18){}
Son(string name,int age):Father(name,age){}
Son(string name, int age,int height):Father(name,age){
this->height=height; //子类新增的属性,自己完成初始化
}
void son_show(){
Father::show();
cout<<"身高:"<<height<<endl;
}
};
int main(){
//Son s("小名",20);
//s.show();
//Son s2("小米",20,167);
//s2.son_show();
Son s3("张飞");
s3.show(); //姓氏:张飞 年龄:18
}
练习:
封装Person 类
name,age,sex
给出show方法要输出上面三条信息
封装Employee 职员 继承自Person
salary, work_id
给出show方法要输出除了Person类中基本的情况之外 再输出salary, work_id
封装Manager 管理者 继承自Employee
position 职位
给出show方法要输出除了Employee类中基本的情况之外 再输出position
我的方法:
#include <iostream>
using namespace std;
class Person{
private:
string name;
string sex;
public:
Person(string n,string s):name(n),sex(s){}
void show(){
cout<<"姓名:"<<name<<endl;
cout<<"性别:"<<sex<<endl;
}
};
class Employee:public Person{
private:
double salary;
int work_id;
public:
Employee(string name,string sex,double salary,int work_id):Person(name,sex){
this->salary=salary;
this->work_id=work_id;
}
void Eshow(){
Person::show();
cout<<"薪水:"<<salary<<endl;
cout<<"工号:"<<work_id<<endl;
}
};
class Manager:public Employee{
private:
string position;
public:
Manager(string name,string sex,double salary,int work_id,string position):Employee(name,sex,salary,work_id){
this->position=position;
}
void Mshow(){
Employee::Eshow();
cout<<"职位:"<<position<<endl;
}
};
int main(){
Person p1("jerry","男");
p1.show();
cout<<"************************"<<endl;
Employee p2("tom","男",3000.4,22121);
p2.Eshow();
cout<<"************************"<<endl;
Manager p3("lisa","女",6000.5,21233,"HR");
p3.Mshow();
}
运行结果:
5.权限
public 在本类中可以访问 在子类中可以访问 全局中可以使用 //父亲
protected 在本类中可以访问 在子类中可以访问 全局中不可以使用 //儿子
private 在本类中可以访问 在子类中不可以访问 全局中不可以使用 //外人
#include <iostream>
using namespace std;
class Father{
public:
string first_name="王";
protected:
string car="link&co";
private:
string password="123456#";
public:
void show(){
cout<<first_name<<endl;
cout<<car<<endl;
cout<<password<<endl;
}
};
class Son:public Father{
public:
void s_show(){
cout<<first_name<<endl;
cout<<car<<endl;
//cout<<password<<endl; 父类私有的 子类中不可以访问
}
};
int main(){
Father f;
f.show();
cout<<"*************"<<endl;
Son s;
s.s_show();
cout<<"*************"<<endl;
//全局相当于外人
cout<<f.first_name<<endl;
//cout<<car<<endl; //保护权限数据在全局中不能访问
//cout<<password<<endl; //私有内容在全局中不能访问
}