第三十三章讲 class(3)

      再说今天的内容之前先把我们昨天留给大家的问题解答一下:
当我们写下:
class Date{ }
哪怕我们什么都不写其实相当于我们已经写下:
——————————————-
class Date{
public:
           Date();


           ~Date();


           Date(const Date&

);


           Date&

operator=(const Date&

);


}
———————————————-
所以,当我们写出一个类名的时候,那么什么都不做,其实编译器已经为我们准备了4个默认函数。
好了,现在重新回到我们的正题来,其实关于Date这个界面我们已经开发得差不多了,所以我们今天来尝试着使用这个库:
———————————-
#include <iostream>#include “Data.h”
int main()
{
My_Code::Date today;

My_Code::Date tomorrow = today;


     tomorow.Add_day(1);

std::cout<<today.day()<<std::endl;


     std::cout<<tomorrow.day()<<std::endl;

return 0;

}
————————————–
我们运行程序可以得到如下结果:
—————-
28
1
—————–
第三十三章讲 class(3)
这就是我们用了两晚上的时间写出来的Date库,但是我们把这个Date类放在名称空间My_Code,所以我们想要使用Date,就必须得这样使:
My_Code::Date
凡是想要使用名称空间中的任何东西,都必须得这样使。
到此处,我们还是发现这个Date库不够完整,就比如说,他还缺少一个能够显示信息的函数,所以我们在class的定义里添加了下面的函数原型:
——————————-

void Show()

———————————-
然后我们可以这样来实现:
————————————–

void Date::Show()

{
     cout<<m<<“/”<<d<<“/”
                  <<y<<endl;


}
————————————–
于是我们可以重新修改上面的主函数:
————————————–
#include “Data.h”
int main()
{
My_Code::Date today;

My_Code::Date tomorrow = today;


     tomorow.Add_day(1);

today.Show();


     tomorrow.Show()
     
return 0;

}
————————————–
运行程序,将得到下面的结果:
————–
2/28/2014
3/1/2014
—————
第三十三章讲 class(3)
现在看来似乎有些完美了,我们从头从未都只使用Date来完成各种操作,我们还可以这样写:
———————————————–
tomorow.Add_day(1).Add_month(2);


————————————————
这将表示两个月后的明天,同样可以实现几年后等等,仔细想了下,对于这个Date库,我们还要实现些什么功能呢?
判断两个对象是不是同一天,还有计算出两个对象之间的差或者是和,不过计算差还有点意义,但是计算和的话就没啥啥意义,就好比,2/28/2014 + 3/8/2014一样,大家有意义吗?但是反过来就不一样了,我们可以用3/8/2014 – 2/28/2014可以得到一个两个对象的差距。
到这里,问大家一个问题,我们可以直接使用tomorrow – today这样的表达式吗?
当然不能,我们平时使用的各种运算符,那是因为编译器在内部已经重载了这些操作符,所以我们如果想要在我们自定义的类使用运算符,我们就必须得重载这些操作符。
——————————————-
Date&

operator-(const Date&

rd)
——————————————–
    这个函数实现起来有些复杂,我在想是留给大家作业呢还是留给大家作业呢?大家可以参考下面我自己实现的这个,然后思考问题出在那里:
———————————————
Date&

Date::operator-(const Date&

rd)
{
if(d <rd.d)
{
m–;

d += 30-rd.d;

}
else
d -= rd.d;

if(m<rd.m)
{
y–;

m = m+12-rd.m;

}
else
m -= rd.m;

if(y<rd.y)
{
cout<<“表达式有误”<<endl;

}
else
y -= rd.y;

return *this;

}
————————————-
不管怎么样,既然我们写出这个实现,那么我们就要测试一下,看看问题出现在那里:
————————————-
Date Diff = tomorrow – today;


Diff.Show();


————————————–
然后我们会看到如同下面的输出:
———————–
2/3/0
———————-
为什么会是这样呢?其实,只是相差两月零1天而已,为什么会是2个月零3天呢?大家一定想起来了,是因为不同的月份有不同的天数,而我们的today正是今天2/28/2014,而二月份正好只有28天,而我们使用30天,所以问题就出在这里,那么该怎么解决呢?这就留给大家去思考了。
现在,我们该来总结一下怎么写出一个高效的类:
———————————–
//Date.h
#pragma once
namespace My_Code{
int leap_year(int n);


      lass Date
{
int m,d,y;

static Date default_day;

public:
enum Month{jan=1,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec };


           Date(int,Month,int);

Date(int,Month);

Date(int);

Date();

ate&

Add_year(int n);

Date&

Add_month(int n);

Date&

Add_day(int n);

inline
int day() const
{

return d;

}
inline Month month() const
{

return Month(m);

}
inline
int year() const
{

return y;

}
            Date(const Date&

);

Date&

operator=(const Date&

);


            Date&

operator-(const Date&

);

void Show();

static
void set_default(int,Month,int);

};

}
——————————————
我的实现是不完整的,大家试着尝试一下找出不完美之处,然后自行修改一下,有问题可以提出(因为字数限制的原因,所以无法把所有代码全部贴出来,我想了下,要不明天把代码发出来吧,然后大家再看看那些地方是不恰当的,然后自己修改验证一下,C++代码是可以重复使用的,大家可以把一些觉得使用的收藏起来,以后开发大型程序的时候或许会派上用场哦,就像我们现在写的这个类,如果以后我想要开发一个个日历或者什么大型软件时,可能会需要在里面插入一个和Date相关的东西,那时候我们可以把今天的Date当成基类去派生我们想要的类就好)。
———————————————-
//Date.cpp
#include “Data.h”
#include <iostream>using namespace std;

namespace My_Code
{
int leap_year(int n)
{
if(n%4 == 0 &

&

n%100 != 0)

return 1;

return 0;

}
Date Date::default_day(28,feb,2014);

void Date::set_default(int d,Month m,int y)
{
Date::default_day = Date(d,m,y);

}
       Date::Date(int dd,Month mm,int yy)
{
if(dd==0)
dd = default_day.day();

if(mm==0)
mm = default_day.month();

if(yy==0)
yy = default_day.year();

int maxday;

switch (mm)
{
case jan:
case may:
case mar:
case jul:
case aug:
case oct:
case dec:
maxday = 31;

break;


           case feb:
maxday = 28 + leap_year(yy);

break;

case apr:
case jun:
case sep:
case nov:
maxday = 30;


                   break;


           default:
cout<<“初始化失败”<<endl;


                   break;

}
if(dd<1 || dd>maxday)
cout<<“初始化失败”<<endl;

d = dd;

m = mm;

y = yy;

}
       ate&

Date::Add_year(int n)
{
if(d==29 &

&

m==2 &

&

leap_year(y+n) != 0)
{
d = 1;

m = 3;

}
y += n;

return *this;

}
      Date&

Date::Add_month(int n)
{
if(n==0)

return *this;

if(n>=0)
{
int temp_y = n/12;

int temp_m = m + n%12;

if(temp_m>12)
{
temp_y++;

m = temp_m-12;

}
y += temp_y;

m = Month(temp_m);

}
if(n<0)
{
cout<<“参数有误”<<endl;

 //关于这里大家可以自行实现,当然如果真不想要负数的话,可以在这里设置抛出异常。
                }

return *this;

}
        …………
         Date::Date(const Date&

t)
{
d = t.d;

m = t.m;

y = t.y;

}
         Date&

Date::operator=(const Date&

t)
{
if(this == &

t)

return *this;

d = t.d;

m = t.m;

y = t.y;

return *this;

}
         …………
         
void Date::Show()
{
cout<<(Month)m<<“/”<<d<<“/”<<y<<endl;

}
}

发表评论