其他分享
首页 > 其他分享> > OPP中级

OPP中级

作者:互联网

C++快速入门

标准输入对象
标准输出对象
while 语句
for 语句
if 语句

一、
demo.cpp

int main()
{
	return 0;
}

输入和输出.cpp

#include<iostream>//cout

int main()
{
	std::cout << "Hello,world!"<<std::endl<< std::endl;//::作用域操作符  std::endl换行

	int v1;
     v1=12;
	std::cout << v1 << std::endl;

	int v2;
	std::cin >> v2;
	std::cout << v2 << std::endl;

	int a1, a2;
	//std::cin >> a1;
	//std::cin >> a2;
	std::cin >> a1 >> a2;//可以连续输入

	std::cout << a1 << "," << a2 << std::endl;
	std::cout << "The sum of" << a1
		<<"and"<<a2<<"is"<<a1 + a2 << std::endl;
  	return 0;
}

二、类
类的头文件 一般写在头文件.h中
销售单
在这里插入图片描述
销售 sales
项目 item
class Sales_item
{
};

Sales_item.h头文件(不完整 需要完善 否则后面的cpp运行报错)

#pragma once
#include<iostream>
using namespace std;//包含string

class Sales_item
{
public:
inline 
double Sales_item::avg_price() const
{
	if (units_sold)
		return revenue / units.sold;
	else
		return 0;
}
	//
};

销售书籍.cpp

#include<iostream>
#include"Sales_item.h"
using namespace std;

int main()
{
	Sales_item book;

	std::cout << "请输入销售的第一本书的信息:" << std::endl;

	cin >> book;

	std::cout << "您输入的信息是:" << endl;
	cout << book << endl;

	return 0;
}

item.cpp

#include<iostream>
#include"Sales_item.h"
using namespace std;

int main()
{
	Sales_item item1, item2;//item1, item2是对象
	cin >> item1 >> item2;
	cout << item1 + item2<<endl;//2个对象加起来
	return 0;
}

while

#include<iostream>

int main()
{
	int sum=0,val=1;
	while (val <= 10)
	{
		sum += val;
		++val;
	}
	std::cout << "Sum of 1 to 10 inclusive is " << sum << std::endl;
	return 0;
}

for.cpp

#include<iostream>

int main()
{
	int sum = 0;
	for (int val = 1;val <= 10;++val)
		sum += val;
	std::cout << "(for语句)Sum of 1 to 10 inclusive is"
		<< sum << std::endl;
	return 0;
}

sum小技巧.cpp

#include<iostream>

int main()
{
	int sum = 0, value;
	//当有输入时数继续循环,没有输入时停止循环
	while (std::cin >> value)
		sum += value;
	std::cout << "Sum is:" << sum << std::endl;
	return 0;
}

这样一直用的没有问题, 但今天突然编译报错了~!报错:“const char *” 类型的实参与 "char " 类型的形参不兼容之类的错误, 函数形参为char的类型直接写入字符串也会报错, 这可就郁闷了, 上网查找竟然没有找到解决方法, 但是在另一个电脑同一个项目就不会报错, 都是VS2017, 一个WIN10家庭版一个WIN10专业版, 这种错误竟然丝毫没有头绪, 中间过程也不废话了, 最后的解决办法其实很简单, 在项目属性->C/C+±>所有选项>语言中的符合模式项>>否即可!!就是这么任性, 记录一下以防以后忘掉了XXXX…

在这里插入图片描述
类定义2

#include<iostream>
#include<string>
using namespace std;
//   销售   项目
class Sales_item
{
public:
	Sales_item(std::string& book, unsigned units, double amount)
		:isbn(book), units_sold(units), revenue(amount)//std::写不写都行
	{}
	double avg_price() const//成员函数
	{
		if (units_sold)
			return revenue / units_sold;
		else
			return 0;
	}
	bool same_isbn(const Sales_item& rhs)const
	{
		return isbn == rhs.isbn;
	}
	void add(const Sales_item &rhs)//会修改
	{
		units_sold += rhs.units_sold;
		revenue += rhs.revenue;
	}
private:string isbn;//书号
	   unsigned units_sold;//销售数量
	   double revenue;//总金额
};
class Person
{

public:
	//成员
//公有成员写在前面
	Person(const string &nm,const string &addr):name(nm),address(addr)//初始化列表
		//把这两个参数保存到私有成员 
{
		/*name = nm;
		address = addr;*/ //和Person中:name(nm), address(addr)一样的效果
}

	//公有成员 可以在类的外部使用
public:string getName() const //不会修改 只读 
{
	return name;
}
public:string getAddress() const//不会修改 只读
{
	return address;
}
	  //一般私有成员写在后面
private:string name;//私有成员 只能在类的内部使用
private:string address;

};
int main()
{
	Person a("张飞","1号");

	//cout << a.name << "," << a.address;私有成员不可调用
	cout << a.getName() << "," << a.getAddress() << endl;

	Sales_item x(string("0-399-8247-1"),2,20.00);
	Sales_item y(string("0-399-82477-1"),6,48.00);

	if (x.same_isbn(y))
		x.add(y);

	cout << "两个销售单的平均价:" << x.avg_price() << endl;

	cout << x.avg_price() << endl;
	cout << y.avg_price() << endl;
	a.getName();
	a.getAddress();

	cout << "Hello 类!" << endl;
	return 0;
}

类定义(2)

#include<iostream>

using namespace std;
class Screen {
	//写在类内部的并定义的函数 叫内联函数 Screen get()  get(index r,index c)
public:
	typedef std::string::size_type index;//别名index 代替所有的std::string::size_type类型

	Screen(index ht = 0, index wd = 0) :contents(ht* wd, 'A'), cursor(0), height(ht), width(wd)//构造函数 内联函数 因为该函数定义在类内部
	{}
	Screen(index ht, index wd, const std::string& conts);
	//get重载函数
	//成员函数的声明
	char get()const;//get 成员函数


	//char get(std::string::size_type r, std::string::size_type c)const //r表示行 c表示列
    inline char get(index r, index c)const; //r表示行 c表示列
	
private:
	std::string contents;//数据成员代表所有文字
	index cursor;//光标位置
	index height, width;
};
Screen::Screen(index ht, index wd, const std::string& conts):contents(conts),cursor(0),height(ht),width(wd)
{}

inline char Screen::get()const//不写inline的函数不是内联函数 写了inline 的函数叫内联函数
{
	return contents[cursor];//返回当前光标位置
}

char Screen::get(index r,index c)const//写作用域 Screen::
{
	index row = r * width;
	return contents[row + c];
}
int main()
{
	Screen a(10,9);
	cout << a.get();
	cout << a.get(2, 8) << endl;

	Screen b(3, 6, "hello screen class") ;//hello' ' 6个 screen 6个 class' '6个
	cout<< b.get()<<endl;
	cout << b.get(0, 4)<<b.get(1,2)<< endl;//hello 01234
	cout << "测试一下" << endl;
	return 0;
}

类定义(3)

#include<iostream>
#include<string>

using namespace std;
class Screen;//类声明

class LinkScreen {
	Screen *window;
	LinkScreen* next;
	LinkScreen* prev;
};
class Y;
class X
{
	//各种成员略
private:
	Y* ptr;
};
class Y
{
	//各种成员略
private:
	X* ptr;
	X obj;
};

//    记录
class Record//这是一个完整的类:类定义,类声明
{

	
public:
	typedef std::size_t size;
	Record() :byte_count(0) {}
	Record(size s) :byte_count(s) {}
	Record(std::string s) :name(s), byte_count(0) {}

	size get_count()const { return byte_count; }
	std::string get_name()const { return name; }

private:
	size byte_count;
	std::string name;//记录名称
};
int main()
{
	Record r;//在堆栈上创建类的对象

	Record* p = new Record;//在堆栈动态创建对象

	delete p;
	//Screen scr; 这个scr对象报错 因为没有定义类Screen 

	Screen *scr;//指针可以
	cout << "hello" << endl;
	return 0;
}

C语言写的类

#include<stdio.h>

struct Person
{
	char name[30];
	char address[100];
};
int main()
{
	struct Person p;
	strcpy(p.name, "Bill");//报错 没有定义strcpy
	strcpy(p.address, "花园");

	printf("hello c!\n");
	printf("%s,%s\n", p.name, p.address);
	return 0;
}

隐含的this指针

this指针

#include<iostream>
#include<string>

using namespace std;

class Person
{
public:
	Person(const std::string& nm, const std::string& addr)
	{
		this->name = nm;
		this->address = addr;
	}
	std::string getName()const
	{
		return this->name;//this指针在这里可写可不写 写了更清楚点
	}
    std::string getAddress()const
    {
		return this->address;
     }
private:
	std::string name;
	std::string address;
};
int main()
{
	Person p("张飞", "花园");
	Person p2("刘备", "花园");
	cout << p.getName() << endl;
	cout << p2.getAddress() << endl;
	return 0;
}

下面的要用this 遇到可以写可不写的时候 建议都写

#include<iostream>
#include<string>

using namespace std;

class Person
{
public:
	Person(const std::string& nm, const std::string& addr)
	{
		this->name = nm;
		this->address = addr;
	}
	std::string getName()const
	{
		return this->name;//this指针在这里可写可不写 写了更清楚点
	}
    std::string getAddress()const
    {
		return this->address;
     }
private:
	std::string name;
	std::string address;
};

class Screen//屏幕上的窗口
{
public:
	typedef std::string::size_type index;
	Screen(index ht = 0, index wd = 0) :contents(ht* wd, 'A '), cursor(0), height(ht),width(wd),access_ctr(0)
	{}
	char get() const { return contents[cursor]; }
	char get(index r, index c)const
	{
		index row = r * width;
		return  contents[row + c];
	}
	Screen& move(index r, index c);//此处不写void 
	Screen& set(index, index, char);
	Screen& set(char);
	const Screen& display(std::ostream& os) const//返回const
	{
		++access_ctr;
		do_display(os);
		return *this;
	}
	Screen display(std::ostream& os)//这是基于上面const的display的重载 不是const
	{
		++access_ctr;//计算display 用了几次
		do_display(os);
		return *this;
	}
private:
	std::string contents;
	index cursor;
	index height, width;
	//可变的
	mutable size_t access_ctr; //计数

	void do_display(std::ostream& os) const
	{
		os << contents;

	}
};
//
//Screen& Screen::move(index r, index c)
//{
//	index row = r * width;
//	cursor = row + c;
//}
Screen&Screen::set(index r, index c, char ch)
{
	index row = r * width;
	contents[row + c]=ch;
	return *this;

}
Screen& Screen::set(char c)
{
	contents[cursor] = c;
	return *this;
}
Screen& Screen::move(index r, index c)
{
	index row = r * width;
	cursor = row + c;
	return *this;//*this 表示间接引用或者解除引用
	//必须使用this指针返回对象 才能写87行的 myScreen.move(2,3).set('C');
}
int main()
{
	Person p("张飞", "花园");
	Person p2("刘备", "花园");

	cout << p.getName() << endl;
	cout << p2.getAddress() << endl;


	Screen myScreen(5, 3);
	cout << myScreen.get() << endl;
	myScreen.set(3, 2, 'B');
	cout << myScreen.get(3,2) << endl;
	//这两行是重点
	//myScreen.move(2, 3);
	//myScreen.set('C');

	//更简单的写法               非const                 const
     myScreen.move(2,3).set('C').display(cout).set('K').display(cout);//这个写法太漂亮!
	 cout << endl;
	 myScreen.move(4, 0).set('X').move(4, 1).set('Y').move(4, 2).set('Z').display(cout);
	 cout << endl;
	cout << myScreen.get() << endl;
	//       const
	myScreen.display(cout);
	cout << endl;

	return 0;
}

类作用域

作用域1

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

void doA()
{
	int a;
	a = 12;
}//a在上面花括号构成的作用域里
void doB()
{
	int b;
	b = 99;
}

class First
{
public:
	int memi;
	double memb;
public:
	void doC()//doC和memi在同一个作用域内可以相互调用
	{
		memi = 22;
	}

	void doD()
	{
		doC();
	}
};
int height;//全局作用域里的变量
class ScreenB
{
public:
	typedef std::string::size_type index;
	void dummy_fcn(index height)
	{
		//cursor = width * height;//这是哪一个height?
		//cursor = width * this->height;
		cursor = width * ::height;//全局作用域的变量height

	}
private:
	index cursor;
	index height, width;
};
class ScreenA
{
public:
	typedef std::string::size_type index;
	char get(index r, index c)const;
	index get_cursor() const;
private:
	std::string contents;
	index cursor;
	index height, width;
 };
ScreenA::index ScreenA::get_cursor() const
//ScreenA::get_cursor()说明get_cursor是ScreenA内的函数 ScreenA::index说明index是ScreenA内部的函数
{
	return cursor;
}
char ScreenA::get(index r,index c) const//在外边加上作用域操作符::
{
	index row = r * width;
	return contents[row + c];
}
int main()
{

	ScreenA::index ht;//作用域::
	ScreenA sa;
	ScreenB sb;
	doA();
	doB();//doB()是全局的 可以使用
	First obj;//先定义对象 
	First* ptr = &obj;
	obj.memi = 12;//通过对象obj使用memi是可以的
	obj.doC();//通过对象 可以使用doC()
	ptr->doC();
	ptr->memi = 99;
	return 0;
}

构造函数

必须用初始化列表的:

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

class Person
{
public:
	//默认构造函数
	Person() :age(0) {}
	//构造函数
	//                              初始化列表       
	Person(const std::string &nm,int a) :name(nm),age(a) {}//  加上const 否则输入"张飞"报错 
public:
	std::string name;
	int age;
};
class Cat
{
public:
	Cat() {}
	//构造函数 要是不写 c++会自动加一个构造函数为 Cat(){}
	Cat(std::string &nm) :name(nm),age(0) {}
	std::string getName() { return this->name; }
	int getAge() { return this->age; }
private:
	std::string name;
	int age;
};
class Dog
{
public:
	Dog():legs(4)
	{
	
	}
private:
	std::string name;
	const int legs;
};
class Sales_item
{
public:
	//explicit (显示的)  消除副作用
	explicit Sales_item(const std::string& book, int units, double price)
		:isbn(book), units_sold(units), revenue(units* price)//初始化列表的顺序 不是固定的
	{}
	                            //加了=""之后 就把Sales_item()函数注释掉否则报错
explicit Sales_item(const std::string& book=" ") :isbn(book), units_sold(0), revenue(0.0) {}//一个形参的有副作用
explicit Sales_item(std::istream& is) { is >> *this; }//一个形参的有副作用
	//构造函数 永远不需要const
explicit Sales_item(int units,double price)//标点,
	{
		this->units_sold = units;
		this->revenue = units * price;
	}
//	Sales_item():units_sold(0),revenue(0.0) {}//isbn的没有初始化 C++会自动初始化
	
	bool same_isbn(const Sales_item& rhs)const
	{
		return isbn == rhs.isbn;
	}
	friend std::istream& operator>>(std::istream&, Sales_item&);
private:
	std::string isbn;
	unsigned units_sold;
	double revenue;
};
inline istream& operator>>(istream& in, Sales_item& s)
{
	double price;
	in >> s.isbn >> s.units_sold >> price;
	if (in)
	
		s.revenue = s.units_sold * price;
	else
		s = Sales_item();
	return in;
	
}

//C->C++
//不能有构造函数 所有成员是public
class Data
{
public:
	int ival;
	char* ptr;
};
class Eata
{
public:
	Eata(int i, char* p) :ival(i), ptr(p) {}
private:
	int ival;
	char* ptr;
};

int main()
{
	Data v = { 9,"hello" };//C语言的写法
	Eata w(9, "hello");//C++的写法
	const int k = 10;
	
	Cat aCat;//不加() 加()表示函数

	Person a("张飞",22);
	Person b;//不加()

	Sales_item item1;//不加()
	Sales_item item2("13-3232-0");

	//if (item2.same_isbn("12-4213-9"))
	//{

	//}
	//if (item2.same_isbn(cin))
	//{

	//}
	Sales_item* p = new Sales_item();//这个()可写可不写 new调用构造函数
	const Sales_item item3;

	Sales_item myobj;//不加() 加了()会当成函数声明

	if (myobj.same_isbn(item2))
	{
		cout << "相同" << endl;
	}
	cout << a.name << endl;
	cout << a.age << endl;

	delete p;//用了new就要用delete 不要写*p 写p
	return 0;
}

友元–友元函数、友元类

普通函数(非成员函数)
类
类的成员函数
#include<iostream>

using namespace std;

class Screen;
class Dog
{
public:
	int foo(Screen& screen);
	
	int koo(Screen& screen);

};
class Screen
{
public:
	friend int calcArea(Screen&);
	friend class Window_Mgr;
	//friend class Dog; 把Dog里面的foo和koo都作为友元
	friend int Dog::foo(Screen&);
	typedef std::string::size_type index;
	//            默认值为0
	Screen(int ht, int wd = 0) :contents(ht* wd, ' '), cursor(0), height(ht), width(wd)
	{}
	//略

	int area() const
	{
		return height * width;
	}

private:
	std::string contents;
	index cursor;
	int height, width;
};

//普通函数
//这个函数不是类的成员函数
int calcArea(Screen& screen)
{
	return screen.height * screen.width;

}
class  Window_Mgr//窗口管理类 --对Screen进行管理
{
public:
	void relocate(int r, int c, Screen& s)//要用到Screen 
	{
		s.height += r;
		s.width += c;
	}
};

int Dog::foo(Screen& screen)
{
	return  screen.height * screen.width;
}

int Dog::koo(Screen&screen)
{
	return screen.area();//公有的area
}

int main()
{
	Screen a(60,100);

	cout << a.area() << endl;

	Window_Mgr wm;
	wm.relocate(20, 100, a);

	Dog dog;
	cout << dog.foo(a) << endl;
	cout << dog.koo(a) << endl;

	cout << calcArea(a) << endl;
	cout << "OK" << endl;
	return 0;
}

static类成员
静态的成员函数 不能使用this指针

不同的类可以有同名的静态成员(属于类,不会和其他类的成员冲突)
可以封装(私有的)

#include<iostream>
#include<string>

using namespace std;

//全局变量
//double interestRate;

class Dog
{
   
};
class Account//账户
{
public:
	Account(std::string name, double money) :
		owner(name), amount(money) {}
	double getAmount() const
	{
		return this->amount;
	}
	void applyint() { amount += amount * interestRate; }
	void deposit(double money)//存钱
	{
		this->amount += money;
	}

static	double rate() { return interestRate; }
static	void rate(double newRate)
	{
		interestRate = newRate;
	}
private:
	std::string owner;//用户名
	double amount;//金额
	static double interestRate;//只有一个 静态的
	//	static double interestRate=0.2;不可以初始化
	static const int period = 30;//静态常量整型 才可以初始化
};
double Account::interestRate = 0.015;

int main()
{
	//interestRate = 0.015;

	Account::rate(0.026);//静态的函数 可以::这样做

	Account a("张三", 1000);
	a.deposit(500);
	Account b("李四", 2000);
	b.deposit(600);

	cout << a.getAmount() << endl;
	cout << b.getAmount() << endl;
	cout << a.rate() << endl;
	a.rate(0.018);
	cout << b.rate() << endl;

	Account::rate(0.02);
	a.applyint();
	b.applyint();
	cout << a.getAmount() << endl;
	cout << b.getAmount() << endl;
	return 0;
}

赋值操作符和复制构造函数

1.对象的定义形式----复制初始化
2.形参与返回值
3.初始化容器元素
4.构造函数与数组元素
1.重载赋值操作符
2.复制和赋值常一起使用
#include<iostream>
#include<string>
#include<vector>

using namespace std;

class Sales_item
{
public:
	//公有的成员
	Sales_item() :units_sold(0), revenue(0.0) 
	{
		cout << "默认构造函数被调用" << endl;
	}
	Sales_item(const std::string& book) 
		:isbn(book), 
		units_sold(0),
		revenue(0.0)
	{
		cout << "构造函数Sales_item(const std::string &book)被用" << endl;
	}

	//复制构造函数
	//const &  把oring 一个一个复制给Sales_item
	Sales_item(const Sales_item& orig)
		:isbn(orig.isbn),
		units_sold(orig.units_sold), 
		revenue(orig.revenue)
	{
		cout << "复制构造函数被调用了!" << endl;
	}
	//赋值操作符
	Sales_item& operator=(const Sales_item&rhs)
	{
		cout << "赋值操作符被调用了!" << endl;
		isbn = rhs.isbn;
		units_sold = rhs.units_sold;
		revenue = rhs.revenue;
		return *this;
	}

private:
	std::string isbn;
	unsigned units_sold;
	double revenue;
};

class NoName
{
public:
	NoName() :pstring(new std::string), i(0), d(0) {}

	NoName(const NoName& other)
		:pstring(new std::string(*(other.pstring))), i(other.i), d(other.d)
	{
		cout << "NoName Copy Constructor" << endl;
	}

	/*NoName(const NoName& other)
		:pstring(other.pstring), i(other.i), d(other.d) {}*///C++自动写的

	NoName& operator=(const NoName& rhs)
	{
		cout << "NoName 赋值操作符" << endl;
		pstring = new std::string;
		*pstring = *(rhs.pstring);

		i = rhs.i;
		d = rhs.d;
		return *this;
	}
private:
	std::string* pstring;
	int i;
	double d;
};
Sales_item foo(Sales_item item)
{
	Sales_item temp;//默认构造函数
	temp = item;//赋值
	return temp;//
}
int main()
{
	NoName x,y;
	NoName z(x);
	x = y;

	Sales_item a;//默认构造函数
	Sales_item b("0-213-3243-X");
	//构造函数
	Sales_item c(b);//复制构造函数

	a = b;//赋值构造函数

	Sales_item item = string("9-999-9999-9");//构造函数

	cout << endl << "试一下foo:" << endl;
	Sales_item  ret;//默认构造
	ret = foo(item);//复制 实参复制到形参

	cout << endl << "试一下vector:" << endl;
	vector<Sales_item> svec(5);

	cout << endl << "试一下数组:" << endl;
	Sales_item primer_eds[] = {
		string("0-210-14523-3"),
		string("3-24-2555-2"),
		string("3-3223-3546-2"),
		Sales_item()
	};
	return 0;
}

析构函数

写了析构函数 就要写复制构造函数和赋值操作符
#include<iostream>

using namespace std;

class Sales_item
{
public:
	//成员(略)
private:
	std::string isbn;
	int units_sold;
	double revenue;
};
class NoName
{
public:
	NoName() :pstring(new std::string), i(0), d(0) 
	{
		//打开文件
		//连接数据库
		//动态分配内存
		cout << "构造函数被调用了!" << endl;
	}

	NoName(const NoName& other);
	~NoName();

	NoName& operator=(const NoName& rhs)
	{
		pstring = new std::string;
		*pstring = *(rhs.pstring);
		i = rhs.i;
		d = rhs.d;
		return *this;
	}
private:
	std::string* pstring;
	int i;
	double d;
};

NoName::NoName(const NoName& other)
{
	pstring = new std::string;
	*pstring = *(other.pstring);
	i = other.i;
	d = other.d;
}
NoName::~NoName()
{
	//关闭文件
	//关闭数据库
	//回收动态分配的内存
	cout << "析构函数被调用了!\n" << endl;
	delete pstring;
}
int main()
{
	NoName a;

	NoName* p = new NoName;//delete和new是一对

	delete p;

	cout << "Hello\n" << endl;
	return 0;
}

深复制、浅复制

在这里插入图片描述

#include<iostream>

using namespace std;

class CDemo
{
public:
	CDemo(int pa, char* cstr)
	{
		this->a = pa;
		this->str = new char[1024];
		strcpy(this->str, cstr);//拷贝
	}
	//复制构造函数没写 C++自动构造一个复制构造函数如下:
	//CDemo(CDemo& obj)
	//{
	//	this->a = obj.a;
	//	this->str = obj.str;//这里不对,要深复制才行,这是浅复制
	//}

	CDemo(CDemo& obj)
	{
		this->a = obj.a;
		this->str = new char[1024];
		if (str != 0)
			strcpy(this->str, obj.str);
	}
	~CDemo()
	{
		delete str;//new和delete 一对的
	}
//private:应该是私有的
public:
	int a;
	char* str;//有指针 要创建构造函数 和 深复制

};

int main()
{
	CDemo A(10, "hello");

	CDemo B = A;//复制  A中的10和hello复制给B
	cout << A.a << ","<<A.str << endl;
	cout << "A:" << A.a << "," << A.str << endl;
	cout << "B:" << B.a << "," << A.str << endl;
	B.a = 8;
	B.str[0] = 'K';
	cout << "修改以后:" << endl;
	cout << "A:" << A.a << "," << A.str << endl;
	cout << "B:" << B.a << "," << B.str << endl;
	return 0;
}

管理指针成员
三种方法

标签:std,index,中级,const,string,int,item,OPP
来源: https://blog.csdn.net/m0_49225991/article/details/110947767