在map中插入自定义类对象

来源:互联网 发布:淘宝上积分在哪儿呢 编辑:程序博客网 时间:2024/04/29 12:47

 点击查看原文

上一篇中讲到了map(在头文件<map>中)和set(在头文件<set>中)的高效,但如果不需要对容器中的元素进行排序或建立映射,那么用vector就足够了,而且它的实现更简单。下面以一个简单的例子介绍一下如何灵活的运用map

假设一个学生有名字和性别两个属性,对应一个编号。那么学生类定义如下:

class student
{
private:
        string name;
        char gender;
public:
        student(string n,char g):name(n),gender(g){} //
初始化列表使属性一次性赋值完毕,否则需要两次
       friend ostream& operator<<(ostream& cout,student &s);   //
定义为friend便可拥有访问private属性的权限
};

ostream& operator<<(ostream& cout,student &s)
{
        cout<<s.name<<" "<<s.gender;
         return cout;
}

在写主函数

int main()
{
       map<string,student> sm;
       student ts("lishuai",'M');
       sm[“001”] = ts;//
检索key=”001”的值,如果存在,用ts覆盖,如果不存在,插入ts
       for(map<string,student>::iterator it = sm.begin();it!=sm.end();it++)
       {
             cout<<(*it).second<<endl;
调用operaotr<<重载函数打印student对象
        }
        system("pause");
        return 0;
}

运行报了一堆错:后来发现最根本问题是无法找到student()无参构造函数。于是在类中添加构造函数

student(){}

后运行正确。结果为

lishuai M

说明在插入过程中,如果没找到对象,就先调用无参构造函数。但这只能构造一个空的对象,那一定还会调用赋值函数填写其属性,赋值函数是编译器自动为我们写的,为了搞清楚这个具体过程,我自己来实现。

class student

{

         private:

                   string name;

                   char gender;

         public:

                   student(){cout<<"Default Constructor"<<endl; name="---------";}//给个空名字

                   student(string n,char g):name(n),gender(g){cout<<"Constructor:"<<name<<endl;}   

                   student& operator=(const student& s);

                   student(const student& s);

                   ~student(){cout<<"Destructor:"<<this->name<<endl;}

                   friend ostream& operator<<(ostream& cout,student &s);            

};

student& student::operator=(const student& s)

{

         cout<<"Assignment:"<<s.name<<endl;

         this->name = s.name;

         this->gender = s.gender;

         return *this;

}

student::student(const student& s)

{

         static char c='a';

         this->name = s.name+c++; //每调用一次,就改变名字

         this->gender = s.gender;

         cout<<"Copy Constructor:"<<this->name<<endl;

}

ostream& operator<<(ostream& cout,student &s)

{

         cout<<s.name<<" "<<s.gender;

         return cout;

}       

        

int main()

{

         map<string,student> sm;

         student ts("lishuai",'M');

         cout<<"begin"<<endl;

         sm["001"]=ts;

         cout<<"end"<<endl;

         for(map<string,student>::iterator it = sm.begin();it!=sm.end();it++)

         {

                   cout<<(*it).second<<endl;

         }       

         system("pause");

         return 0;

}

运行结果:

Constructor:lishuai

begin

Default Constructor                     //构造空对象1

Copy Constructor:---------a               //构造空对象2

Copy Constructor:---------ab             //构造空对象3

Destructor:---------a                     //析构空对象2

Destructor:---------                      //析构空对象1

Assignment:lishuai                                                //给对象3赋值

end

lishuai M

可以看到,在插入的过程中,首先调用1次无参构造函数,然后调用2次复制构造函数依次复制前一个创建的对象,再调用两次析构函数析构头2个空对象,最后调用一次赋值函数。很有意思啊!

我要强调的一点就是,当我们自定义了有参构造函数,编译器就不再为我们添加默认构造函数了,所以一定要记得加上一个无参构造函数,即使里面什么都不写,否则就可能遇到我上面的那个问题。其他的如赋值和析构函数可根据情况,自己定义或用编译器提供的。

上面我们是用map实现了编号和学生的对应关系。还可以在此基础上建立班级号与全班学生的对应关系:

map< int , map<string,student> > clas; //在两个>之间一定要加 空格

clas[1]=sm;      //sm是班内学生映射map

clas[1][“001”] = st; //st 是学生对象

很简单吧,呵呵。

原创粉丝点击