第三十五讲 浅出class(1)

       如果说我们的Date类给我们打开了class的大门而部分朋友又不得而进,那么今天我们的浅出class将会带大家真正的走进这扇门。
如同struct一样,class的存在也是为了自定义一个类型,但是他又不像C语言里的struct,C语言里的struct虽然说是定义一个类型,但是他其实只是一个数据结构,而对于class,他不只是一个简单的数据结构,他是面向对象的数据封装,所以他不但有数据,还有方法和属性。
那么怎么定义一个类?相信现在大家都不陌生,C++的关键字class就是定义一个类的关键字,而在关键字后面的名词就是我们要定义的类的名字,如同下面,我们要定义一个Time管理时间的类:
———————————–
class Time{
};
————————————–
一个类是一句语句,所以必须得加上“;”来结束。我们把各种方法数据全都放在这对花括号中声明或者直接定义。
现在大家还记得我们在三十一讲里面曾给大家留了一个问题吗?说以前不如说现在,就拿上面我们的Time类来说吧,大家是不是看到了,我们在花括号中什么都没写,但是我们却可以这样使:
———————————
1).Time t1;


2).Time t2(t1);


3).Time t3;


4).t3 = t2;


————————————
第一句,我们声明了一个对象t1,第二句,我们声明另一个对象t2,然后使用t1初始化他,第三四句我们声明了一个t3,然后用t2初始化t3,当然这里面不同的是t2的初始化使用的是复制构造函数,而t3的初始化使用的是赋值复制操作。
我们什么都没写,却能够实现这么多功能,是不是觉得很有意思呢?如同第三十二讲里面我们所说,当我们这样写下一个类时,什么都不写,编译器会默默的为为什么准备四个函数:
——————————
1)默认构造函数
2)默认析构函数
3)默认复制构造函数
4)默认赋值赋值操作符
——————————–
对于这些默认函数,如果我们没有啥要求的话,可以欣然接受,如果我们不想要呢?那很简单,我们只要把这些函数再写一遍就好,就比如:
————————————————-
class Time{
public:
           Time(int hh,int mm,int ss);
protected:
          
int h,m,s;

};
—————————————————-
这样一来,我们就显示声明了我们的构造函数,如果这时我们再去尝试上面我们的操作的话,编译器就会报错了,为什么早些时候行险招不行了呢?原因是因为我们声明了自己的构造函数,所以编译器自己就不会再认可所谓的默认构造函数了,这时,如果我们还想像刚才那样写的话,只能自己再声明一个构造函数,让他没有参数:
————————————–
class Time{
public:
           Time(int hh,int mm,int ss);
           Time();
protected:
          
int h,m,s;

};
—————————————————-
现在我们又可以像刚才那样使用了,因为我们声明了一个和默认构造函数一样的构造函数,说了这么多,到底什么是构造函数呢?构造函数就是一个和类名相同的函数,而且必须是没有返回值的函数,像上面的两个都是构造函数。如果我们在构造函数前面添加“~”的话,构造函数就变成了析构函数,析构函数说得简单些,就是垃圾回收站,如果我们构造函数又用到动态分配,那么我们就要在析构函数中来回收我们分配的内存。
————————————–
class Time{
public:
           Time(int hh,int mm,int ss);
           Time();
           ~Time();
protected:
          
int h,m,s;

};
—————————————————-
     不过说起来遗憾,今天举的这个例子有点瑕疵,不能够将这个特性展现出来,不过会有机会的。现在,我们在为我们的类添加6个函数,分别用来设置时间和获取时间:
——————————————-
class Time{
public:
           Time(int hh,int mm,int ss);
           Time();
           ~Time();
           
void SetTime_h(int h);


          
int GetTime_h();


          
void SetTime_m(int m);


          
int GetTime_m();


          
void SetTime_s(int s);


          
int GetTime_s();


          void  Show();


protected:
          
int m_h,m_m,m_s;

};
—————————————————-
现在我们可以来使用这个我们这个类,对于类的对象,我们可以在栈创建,也可以在堆上创建,下面我们是在栈建一个Time对象:
————–
Time t1;
————–
这想必是大家最为熟悉的建立对象的方式了,接下来我们看看怎么在对上创建一个对象呢?其实简单点说,栈上创建直接声明对象,而堆上就是动态分配对象空间,栈的对象会随着作用块的结束而销毁,但是堆上的却需要手动销毁:
————————————
if(int i == 5)
{
     Time t2 == XX;


     /////////
};

//当if代码块结束后,t2也就随之消失
Time *t3 = new Time();


//而t3,如果不手动释放,就会一直存在
———————————————
大家一定看到了,我们这里使用了一个关键字new,如果大家还记得我们说C语言的时候用过malloc的话,那么现在大家肯定联想到new的功能就是malloc了,不过他比malloc好用得多,和malloc不同的是他不是函数,而是一个操作符,所以有new操作符申请的内存,得由操作符来释放,这个操作符就是delete,如上,如果我们想要释放t3,我们可以这样使:delete t3;
至此,我们来测试一下我们的Time类:
———————————-
 My_Code::Time t1;

My_Code::Time *t2 = new My_Code::Time();

t1.SetTime_h(22);

t1.SetTime_m(10);

t1.SetTime_s(30);

t2 = &

t1;

t1.Show();

t2->Show();


—————————————
运行之后,我们会得到下面的结果:
———————-
22:10:30
22:10:30
———————-
大家一定觉得好奇,我们前些天说了一个Date的类,今天说了一个Time的类,要是把这两个类连起来那就好了,这是我们将会说到的内容,现在大家思考一个问题,怎么才能让我们这个类变得更加效率些呢?

发表评论