上一讲我们说了泛化的复制构造函数,现在我们回来继续看看map,但是再说继续说map之前我觉得我们有必要先把pair弄清楚,其实也没什么好说的了,但是有一个函数我们是一定要知道的:
——————————–
template<typename T,typename U>
pair<T,U>make_pair(T&
t,U&
u){
return pair<T,U>(t,u);
}
———————————
不难发现,这是一个生成pair的函数,我们可以直接使用这个函数得到一个pair,而不必去指明pair类型。关于pair,我们说到这里就差不多了,他的存在多数是为了作为辅助来用,所以我们现在继续回来看看map,在上上讲里我们说了map里面的一些必要的typedef,所以现在我们来接着往下看关于map的一些操作:
———————————–
template<typename Key,typename T,typename Cmp=less<Key>,
typename A=allocator<pair<const Key,T
>>>
class map{
public:
/////
// ///
mapped_type&
operator[](const Key_type&
k);
/////
};
————————————-
这个操作符对现在的我们来说已经司空见惯了,不过不能否认这是一个极为好用的操作,因为我们通常都是用这个下标操作符来操作map的,比如:
————————————
void f(){
map<string, int>m;
m["
Math"
] = 80;
m["
English"
] = 92;
m["
Chinese"
] = 85;
map<string, int>::iterator it = m.begin();
while (it != m.end()){
cout <<it->
first <<"
t"
<<it->second <<endl;
it++;
}
}
———————————-
还记得以前给大家的一个练习吗?那是一位同学提出来的,就是怎么设计一个学生成绩的类,当时我把这个任务扔给大家,因为我想大家肯定有办法解决这个问题,现在我们再回去看这个问题,是不是发觉很简单了呢?如同上面一样,我们用一个map来储存成绩,然后再用map来存储学生姓名和成绩:
———————————–
map<string,map<string,double>>
———————————-
听起来有些复杂,确实是有些复杂的,不是正好我们说到map吗?好啊,反正就算是小试牛刀吧,我就简单的弄个出来看看吧:
———————————–
//Students.h
#ifndef _STUDENTS_H_
#define _STUDENTS_H_
#include <map>
#include <string>
using namespace std;
typedef map<string,double>Data_type;
typedef map<string,Data_type>MyType;
namespace My_Code{
class Students{
public:
Students();
~Students();
void AddStudent(const string&
name,Data_type&
data);
Data_type&
GetScore(const string&
name);
MyType&
GetName();
private:
MyType _name;
};
}
#endif
————————————
实现也很简单,仅作为参考:
————————————
//Students.cpp
#include "
Students.h"
using namespace My_Code;
Students::Students()
{
_name = MyType();
}
Students::~Students()
{
}
void Students::AddStudent(const string&
name,Data_type&
data){
_name[name] = data;
}
Data_type&
Students::GetScore(const string&
name){
return _name[name];
}
MyType&
Students::GetName(){
return _name;
}
———————————
然后,我们可以这样用:
———————————–
//TestStudents.cpp
#include <iomanip>
#include <iostream>
#include "
Students.h"
using namespace std;
using namespace My_Code;
int main()
{
Students s;
Data_Type m;
m["
Math"
] = 60;
m["
English"
] = 70;
m["
Chinese"
] = 80;
s.AddStudent("
ZhangSan"
,m);
//为了方便,所以我们都使用同一份成绩
s.AddStudent("
LiSi"
,m);
s.AddStudent("
WangEr"
,m);
MyType::iterator it = s.GetName().begin();
while(it != s.GetName().end()){ //遍历所有学生和打印出其成绩
cout<<it->
first<<"
:n"
;
Data_type::iterator _it = it->second.begin();
while(_it != it->second.end()){
cout<<setw(20)<<_it->
first<<"
: "
<<_it->second<<endl;
_it++;
}
it++;
}
_it = s.GetScore("
ZhangSan"
).begin();
cout<<"
ZhangSan:n"
;
while(_it != s.GetScore("
ZhangSan"
).end()){ //获取ZhangSan的成绩
cout<<setw(20)<<_it->
first<<"
: "
<<_it->second<<endl;
_it++;
}
return 0;
}
————————————–
这个类使用起来有些复杂不人性化,只要我们愿意,我们可以把写得更加好用一些,当然碍于篇幅的原因,这里我们就不多说了,希望曾经提问的同学还能够坚持下去,能够看到今天我们的实现方案,虽然不能拿出去商用,但可以作为参考,我坚持C++的原因就是这里:100个Java程序员写出的代码都是一种风格,而100个C++程序员写出来的程序就有100种风格。晕死,说了这么多,还是没说到重点,重点就是我们今天所说的operator[]的应用啦,我们使用map,很多情况下是通过operator[]来使用的。
今天好像说得不少了哦,算了吧,今天就先到这里吧,我们下周再见。
=================================
回复D直接查看目录
原文始发于微信公众号(
C/C++的编程教室
):第七十七讲 细说map(3)
|