//date.h#ifndef __DATE_H__#define __DATE_H__classDate{//日期类private:int year;//年int month;//月int day;//日int totalDays;//该日期是从公元元年1月1日开始的第几天public:Date(int year,int month,int day);//用年、月、日构造日期intgetYear()const{return year;}intgetMonth()const{return month;}intgetDay()const{return day;}intgetMaxDay()const;//获得当月有多少天boolisLeapYear()const{//判断当年是否为闰年return year %4==0&& year %100!=0|| year %400==0;}voidshow()const;//输出当前日期//计算两个日期之间差多少天 intoperator-(const Date& date)const{return totalDays - date.totalDays;}};#endif//__DATE_H__
//date.cpp#include"date.h"#include<iostream>#include<cstdlib>usingnamespace std;namespace{//namespace使下面的定义只在当前文件中有效//存储平年中某个月1日之前有多少天,为便于getMaxDay函数的实现,该数组多出一项constint DAYS_BEFORE_MONTH[]={0,31,59,90,120,151,181,212,243,273,304,334,365};}
Date::Date(int year,int month,int day):year(year),month(month),day(day){if(day <=0|| day >getMaxDay()){
cout <<"Invalid date: ";show();
cout << endl;exit(1);}int years = year -1;
totalDays = years *365+ years /4- years /100+ years /400+ DAYS_BEFORE_MONTH[month -1]+ day;if(isLeapYear()&& month >2) totalDays++;}int Date::getMaxDay()const{if(isLeapYear()&& month ==2)return29;elsereturn DAYS_BEFORE_MONTH[month]- DAYS_BEFORE_MONTH[month -1];}void Date::show()const{
cout <<getYear()<<"-"<<getMonth()<<"-"<<getDay();}
//Array.h#ifndef ARRAY_H#define ARRAY_H#include<cassert>//数组类模板定义template<classT>classArray{private:
T* list;//T类型指针,用于存放动态分配的数组内存首地址int size;//数组大小(元素个数)public:Array(int sz =50);//构造函数Array(const Array<T>&a);//拷贝构造函数~Array();//析构函数
Array<T>&operator=(const Array<T>&rhs);//重载"="使数组对象可以整体赋值
T &operator[](int i);//重载"[]",使Array对象可以起到C++普通数组的作用const T &operator[](int i)const;//"[]"运算符的const版本operator T *();//重载到T*类型的转换,使Array对象可以起到C++普通数组的作用operatorconst T *()const;//到T*类型转换操作符的const版本intgetSize()const;//取数组的大小voidresize(int sz);//修改数组的大小};//构造函数template<classT>
Array<T>::Array(int sz){assert(sz >=0);//sz为数组大小(元素个数),应当非负
size = sz;// 将元素个数赋值给变量size
list =new T [size];//动态分配size个T类型的元素空间}//析构函数template<classT>
Array<T>::~Array(){delete[] list;}//拷贝构造函数template<classT>
Array<T>::Array(const Array<T>&a){//从对象x取得数组大小,并赋值给当前对象的成员
size = a.size;//为对象申请内存并进行出错检查
list =new T[size];// 动态分配n个T类型的元素空间//从对象X复制数组元素到本对象 for(int i =0; i < size; i++)
list[i]= a.list[i];}//重载"="运算符,将对象rhs赋值给本对象。实现对象之间的整体赋值template<classT>
Array<T>&Array<T>::operator=(const Array<T>& rhs){if(&rhs !=this){//如果本对象中数组大小与rhs不同,则删除数组原有内存,然后重新分配if(size != rhs.size){delete[] list;//删除数组原有内存
size = rhs.size;//设置本对象的数组大小
list =new T[size];//重新分配n个元素的内存}//从对象X复制数组元素到本对象 for(int i =0; i < size; i++)
list[i]= rhs.list[i];}return*this;//返回当前对象的引用}//重载下标运算符,实现与普通数组一样通过下标访问元素,并且具有越界检查功能template<classT>
T &Array<T>::operator[](int n){assert(n >=0&& n < size);//检查下标是否越界return list[n];//返回下标为n的数组元素}template<classT>const T &Array<T>::operator[](int n)const{assert(n >=0&& n < size);//检查下标是否越界return list[n];//返回下标为n的数组元素}//重载指针转换运算符,将Array类的对象名转换为T类型的指针,//指向当前对象中的私有数组。//因而可以象使用普通数组首地址一样使用Array类的对象名template<classT>
Array<T>::operator T *(){return list;//返回当前对象中私有数组的首地址}template<classT>
Array<T>::operatorconst T *()const{return list;//返回当前对象中私有数组的首地址}//取当前数组的大小template<classT>int Array<T>::getSize()const{return size;}// 将数组大小修改为sztemplate<classT>void Array<T>::resize(int sz){assert(sz >=0);//检查sz是否非负if(sz == size)//如果指定的大小与原有大小一样,什么也不做return;
T* newList =new T [sz];//申请新的数组内存int n =(sz < size)? sz : size;//将sz与size中较小的一个赋值给n//将原有数组中前n个元素复制到新数组中for(int i =0; i < n; i++)
newList[i]= list[i];delete[] list;//删除原数组
list = newList;// 使list指向新数组
size = sz;//更新size}#endif//ARRAY_H
//accumulator.h#ifndef __ACCUMULATOR_H__#define __ACCUMULATOR_H__#include"date.h"classAccumulator{//将某个数值按日累加private:
Date lastDate;//上次变更数值的时期double value;//数值的当前值double sum;//数值按日累加之和public://构造函数,date为开始累加的日期,value为初始值Accumulator(const Date &date,double value):lastDate(date),value(value),sum(0){}//获得到日期date的累加结果doublegetSum(const Date &date)const{return sum + value *(date - lastDate);}//在date将数值变更为valuevoidchange(const Date &date,double value){
sum =getSum(date);
lastDate = date;this->value = value;}//初始化,将日期变为date,数值变为value,累加器清零voidreset(const Date &date,double value){
lastDate = date;this->value = value;
sum =0;}};#endif//__ACCUMULATOR_H__
//account.h#ifndef __ACCOUNT_H__#define __ACCOUNT_H__#include"date.h"#include"accumulator.h"#include<string>classAccount{//账户类private:
std::string id;//帐号double balance;//余额staticdouble total;//所有账户的总金额protected://供派生类调用的构造函数,id为账户Account(const Date &date,const std::string &id);//记录一笔帐,date为日期,amount为金额,desc为说明voidrecord(const Date &date,double amount,const std::string &desc);//报告错误信息voiderror(const std::string &msg)const;public:const std::string &getId()const{return id;}doublegetBalance()const{return balance;}staticdoublegetTotal(){return total;}//存入现金,date为日期,amount为金额,desc为款项说明virtualvoiddeposit(const Date &date,double amount,const std::string &desc)=0;//取出现金,date为日期,amount为金额,desc为款项说明virtualvoidwithdraw(const Date &date,double amount,const std::string &desc)=0;//结算(计算利息、年费等),每月结算一次,date为结算日期virtualvoidsettle(const Date &date)=0;//显示账户信息virtualvoidshow()const;};classSavingsAccount:public Account {//储蓄账户类private:
Accumulator acc;//辅助计算利息的累加器double rate;//存款的年利率public://构造函数SavingsAccount(const Date &date,const std::string &id,double rate);doublegetRate()const{return rate;}virtualvoiddeposit(const Date &date,double amount,const std::string &desc);virtualvoidwithdraw(const Date &date,double amount,const std::string &desc);virtualvoidsettle(const Date &date);};classCreditAccount:public Account {//信用账户类private:
Accumulator acc;//辅助计算利息的累加器double credit;//信用额度double rate;//欠款的日利率double fee;//信用卡年费doublegetDebt()const{//获得欠款额double balance =getBalance();return(balance <0? balance :0);}public://构造函数CreditAccount(const Date &date,const std::string &id,double credit,double rate,double fee);doublegetCredit()const{return credit;}doublegetRate()const{return rate;}doublegetFee()const{return fee;}doublegetAvailableCredit()const{//获得可用信用if(getBalance()<0)return credit +getBalance();elsereturn credit;}virtualvoiddeposit(const Date &date,double amount,const std::string &desc);virtualvoidwithdraw(const Date &date,double amount,const std::string &desc);virtualvoidsettle(const Date &date);virtualvoidshow()const;};#endif//__ACCOUNT_H__