【c++思维导图与代码示例】07 多态性

  • Post author:
  • Post category:其他


【c++思维导图与代码示例】07 多态性



思维导图:

在这里插入图片描述



代码示例:

  • 示例1:
/*************************************************
*
**Description: 将 + 、- 重载为复数类的成员函数,了解双目运算符重载的过程
**              

** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :7-1.cpp
** 
*
***************************************************/
#include <iostream>
using namespace std;

class Complex {	//复数类定义
public:	//外部接口
	Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) { }	//构造函数
	Complex operator + (const Complex &c2) const;	//运算符+重载成员函数
	Complex operator - (const Complex &c2) const;	//运算符-重载成员函数
	void display() const;	//输出复数
private:	//私有数据成员
	double real;	//复数实部
	double imag;	//复数虚部
};	

Complex Complex::operator + (const Complex &c2) const {	//重载运算符函数实现
	return Complex(real + c2.real, imag + c2.imag); //创建一个临时无名对象作为返回值
}

Complex Complex::operator - (const Complex &c2) const {	//重载运算符函数实现
	return Complex(real - c2.real, imag - c2.imag); //创建一个临时无名对象作为返回值
}

void Complex::display() const {
	cout << "(" << real << ", " << imag << ")" << endl;
}

int main() {	//主函数
	Complex c1(5, 4), c2(2, 10), c3;	//定义复数类的对象
	cout << "c1 = "; c1.display();
	cout << "c2 = "; c2.display();
	c3 = c1 - c2;	//使用重载运算符完成复数减法
	cout << "c3 = c1 - c2 = "; c3.display();
	c3 = c1 + c2;	//使用重载运算符完成复数加法
	cout << "c3 = c1 + c2 = "; c3.display();
	return 0;
}

  • 示例2:
/*************************************************
*
**Description: 将单目运算符 ++ 、-- 重载为时钟类的成员函数,了解单目运算符重载的过程
**              ++ 、-- 在变量前,要在实现表达式之前先算++、--
                ++ 、-- 在变量后,要在实现表达式结束之后再算++、--
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :7-2.cpp
** 
*
***************************************************/
#include <iostream>
using namespace std;
class Clock	{	//时钟类声明定义
public:	//外部接口
	Clock(int hour = 0, int minute = 0, int second = 0);
	void showTime() const;
	Clock& operator ++ ();	//前置单目运算符重载
	Clock operator ++ (int);	//后置单目运算符重载
private:	//私有数据成员
	int hour, minute, second;
};

Clock::Clock(int hour/* = 0 */, int minute/* = 0 */, int second/* = 0 */) {	//构造函数
	if (0 <= hour && hour < 24 && 0 <= minute && minute < 60 && 0 <= second && second < 60) {
		this->hour = hour;
		this->minute = minute;
		this->second = second;
	} else
		cout << "Time error!" << endl;
}

void Clock::showTime() const {	//显示时间函数
	cout << hour << ":" << minute << ":" << second << endl;
}

Clock & Clock::operator ++ () {	//前置单目运算符重载函数
	second++;
	if (second >= 60) {
		second -= 60;
		minute++;
		if (minute >= 60) {
			minute -= 60;
			hour = (hour + 1) % 24;
		}
	}
	return *this;
}

Clock Clock::operator ++ (int) {	//后置单目运算符重载
	//注意形参表中的整型参数
	Clock old = *this;
	++(*this);	//调用前置“++”运算符
	return old;
}

int main() {
	Clock myClock(00, 00, 00);  //初始化显示时间
	cout << "First time output: ";
	myClock.showTime();
	cout << "Show myClock++:    ";
	(myClock++).showTime();
	cout << "Show ++myClock:    ";
	(++myClock).showTime();
    
    system("pause");
	return 0;
}


  • 示例3:
/*************************************************
*
**Description:
        将+、‐(双目)重载为非成员函数,并将其声明为复数类的友元,两个操作数都是复数类的常引用。

        • 将<<(双目)重载为非成员函数,并将其声明为复数类的友元,它的左操作数是
            std::ostream引用,右操作数为复数类的常引用,返回std::ostream引用,用以支持下面形式的输出:
                cout << a << b;该输出调用的是:operator << (operator << (cout, a), b);
                
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :7-3.cpp
** 
*
***************************************************/
#include <iostream>
using namespace std;

class Complex {	//复数类定义
public:	//外部接口
	Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) { }	//构造函数
	friend Complex operator + (const Complex &c1, const Complex &c2);	//运算符+重载
	friend Complex operator - (const Complex &c1, const Complex &c2);	//运算符-重载
	friend ostream & operator << (ostream &out, const Complex &c);		//运算符<<重载
private:	//私有数据成员
	double real;	//复数实部
	double imag;	//复数虚部
};	

Complex operator + (const Complex &c1, const Complex &c2) {	//重载运算符函数实现
	return Complex(c1.real + c2.real, c1.imag + c2.imag);
}

Complex operator - (const Complex &c1, const Complex &c2) {	//重载运算符函数实现
	return Complex(c1.real - c2.real, c1.imag - c2.imag);
}

ostream & operator << (ostream &out, const Complex &c) {	//重载运算符函数实现
	out << "(" << c.real << ", " << c.imag << ")";
	return out;
}

int main() {	//主函数
	Complex c1(5, 4), c2(2, 10), c3;	//定义复数类的对象
	cout << "c1 = " << c1 << endl;
	cout << "c2 = " << c2 << endl;
	c3 = c1 - c2;	//使用重载运算符完成复数减法
	cout << "c3 = c1 - c2 = " << c3 << endl;
	c3 = c1 + c2;	//使用重载运算符完成复数加法
	cout << "c3 = c1 + c2 = " << c3 << endl;

    system("pause");
	return 0;
}

  • 示例4:
/*************************************************
*
**Description: 通过虚函数实现运行时多态举例---*(修改上节 之前   类型转换的规则举例 )
             
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :7-4.cpp
** 
*
***************************************************/
/*
例 类型转换规则举例
#include <iostream>
using namespace std;
class Base1 { //基类Base1定义
public:
    void display() const {
        cout << "Base1::display()" << endl;
    }
};
class Base2: public Base1 { //公有派生类Base2定义
public:
    void display() const {
        cout << "Base2::display()" << endl;
    }
};
class Derived: public Base2 { //公有派生类Derived定义
public:
    void display() const {
        cout << "Derived::display()" << endl;
    }
};
void fun(Base1 *ptr) {  //参数为指向基类对象的指针
    ptr->display();     //"对象指针->成员名"
}
int main() {    //主函数
    Base1 base1;    //声明Base1类对象
    Base2 base2;    //声明Base2类对象
    Derived derived;    //声明Derived类对象
    fun(&base1);    //用Base1对象的指针调用fun函数
    fun(&base2);    //用Base2对象的指针调用fun函数
    fun(&derived);     //用Derived对象的指针调用fun函数
    return 0;
}
*/


// 改进后的程序
#include <iostream>
using namespace std;
class Base1 { //基类Base1定义
public:
	virtual void display() const;	//虚函数
};
void Base1::display() const {
	cout << "Base1::display()" << endl;
}

class Base2: public Base1 { //公有派生类Base2定义
public:
	void display() const;	//覆盖基类的虚函数
};
void Base2::display() const {
	cout << "Base2::display()" << endl;
}

class Derived: public Base2 { //公有派生类Derived定义
public:
	void display() const;	//覆盖基类的虚函数
};
void Derived::display() const {
	cout << "Derived::display()" << endl;
}

void fun(Base1 *ptr) { //参数为指向基类对象的指针
	ptr->display();	//"对象指针->成员名"
}

int main() {	//主函数
	Base1 base1;	//定义Base1类对象
	Base2 base2;	//定义Base2类对象
	Derived derived;	//定义Derived类对象

	fun(&base1);	//用Base1对象的指针调用fun函数
	fun(&base2);	//用Base2对象的指针调用fun函数
	fun(&derived);	//用Derived对象的指针调用fun函数

    system("pause");
	return 0;
}


  • 示例5:
/*************************************************
*
**Description: 通过虚函数实现运行时多态举例---*(修改上节 之前   类型转换的规则举例 )
             
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :7-5.cpp
** 
*
***************************************************/
/*
例 类型转换规则举例
#include <iostream>
using namespace std;
class Base1 { //基类Base1定义
public:
    void display() const {
        cout << "Base1::display()" << endl;
    }
};
class Base2: public Base1 { //公有派生类Base2定义
public:
    void display() const {
        cout << "Base2::display()" << endl;
    }
};
class Derived: public Base2 { //公有派生类Derived定义
public:
    void display() const {
        cout << "Derived::display()" << endl;
    }
};
void fun(Base1 *ptr) {  //参数为指向基类对象的指针
    ptr->display();     //"对象指针->成员名"
}
int main() {    //主函数
    Base1 base1;    //声明Base1类对象
    Base2 base2;    //声明Base2类对象
    Derived derived;    //声明Derived类对象
    fun(&base1);    //用Base1对象的指针调用fun函数
    fun(&base2);    //用Base2对象的指针调用fun函数
    fun(&derived);     //用Derived对象的指针调用fun函数
    return 0;
}
*/


// 改进后的程序
#include <iostream>
using namespace std;
class Base1 { //基类Base1定义
public:
	virtual void display() const;	//声明虚函数
};
void Base1::display() const {    //函数实现
	cout << "Base1::display()" << endl;
}

class Base2: public Base1 { //公有派生类Base2定义
public:
	void display() const;	//覆盖基类的虚函数
};
void Base2::display() const {
	cout << "Base2::display()" << endl;
}

class Derived: public Base2 { //公有派生类Derived定义
public:
	void display() const;	//覆盖基类的虚函数   
/*派生类可以不显式地用virtual声明虚函数,这时系统就会用以下规则来判断派生类
的一个函数成员是不是虚函数:
 该函数是否与基类的虚函数有相同的名称、参数个数及对应参数类型;
 该函数是否与基类的虚函数有相同的返回值或者满足类型兼容规则的指针、引用型的返回值;
 如果从名称、参数及返回值三个方面检查之后,派生类的函数满足上述条件,就会自动确定为虚函数。这时,派生类的虚函数便覆盖了基类的虚函数。
 派生类中的虚函数还会隐藏基类中同名函数的所有其它重载形式。
 一般习惯于在派生类的函数中也使用virtual关键字,以增加程序的可读性。 */

};
void Derived::display() const {
	cout << "Derived::display()" << endl;
}

void fun(Base1 *ptr) { //参数为指向基类对象的指针
	ptr->display();	//"对象指针->成员名"
}

int main() {	//主函数
	Base1 base1;	//定义Base1类对象
	Base2 base2;	//定义Base2类对象
	Derived derived;	//定义Derived类对象

	fun(&base1);	//用Base1对象的指针调用fun函数
	fun(&base2);	//用Base2对象的指针调用fun函数
	fun(&derived);	//用Derived对象的指针调用fun函数

    system("pause");
	return 0;
}


  • 示例6:
/*************************************************
*
**Description: 抽象类举例 (纯虚函数)

** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :7-6.cpp
** 
*
***************************************************/

#include <iostream>
using namespace std;

class Base1 { //基类Base1定义
public:
	virtual void display() const = 0;	//纯虚函数
};

class Base2: public Base1 { //公有派生类Base2定义
public:
	void display() const;	//覆盖基类的虚函数
};
void Base2::display() const {
	cout << "Base2::display()" << endl;
}

class Derived: public Base2 { //公有派生类Derived定义
public:
	void display() const;	//覆盖基类的虚函数
};
void Derived::display() const {
	cout << "Derived::display()" << endl;
}

void fun(Base1 *ptr) { //参数为指向基类对象的指针
	ptr->display();	//"对象指针->成员名"
}

int main() {	//主函数
	Base2 base2;	//定义Base2类对象
	Derived derived;	//定义Derived类对象
	fun(&base2);	//用Base2对象的指针调用fun函数
	fun(&derived);	//用Derived对象的指针调用fun函数
	return 0;
}




  • 示例7:
/*************************************************
*
**Description: 声明一个 Point 类,有坐标_x,_y两个成员变量,
                对 Point 类重载“++”(自增)、“--”(自减)运算符,实现对坐标值的改变

** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :7-7.cpp
** 
*
***************************************************/
#include <iostream>
using namespace std;

class Point
{
	int _x, _y;
public:
	Point(int x=0, int y=0) : _x(x), _y(y) {}
	Point& operator++();
	Point operator++(int);
	Point& operator--();
	Point operator--(int);
	friend ostream& operator << (ostream& o, Point& p);
};

Point& Point::operator++()
{
	_x++;
	_y++;
	return *this;
}
/* ++i 在C++里面的定义最后返回的是被++的对象的引用(系统就是这么实现的),所以++i可以作为左值,即可以写:++i=3  */

//后缀式操作符接受一个额外的int型形参(不会使用它,仅做区分用)
Point Point::operator++(int)
{
	Point temp = *this;
	++*this; //复用了前缀++的重载
	return temp;

//后缀式版本中,返回值是尚未自增的原值,但对象本身已经做了自增操作了。

}
/* i++在C++里面的定义是,最后返回的是被++的对象的值(系统就是这么实现的),所以i++不可以作为左值,即不可以写:i++=3 */

Point& Point::operator--()
{
	_x--;
	_y--;
	return *this;
}

Point Point::operator--(int)
{
	Point temp = *this;
	--*this;
	return temp;
}

//友元函数,返回值类型为ostream&,可以支持<<级连操作
ostream& operator << (ostream& o, Point& p) {
	o << '(' << p._x << ", " << p._y << ')';
	return o;
}

int main()
{
	Point p(1, 2);
	cout << p << endl;
	cout << p++ << endl;
	cout << ++p << endl;
	cout << p-- << endl;
	cout << --p << endl;

    system("pause");
	return 0;
}

  • 示例8:
/*************************************************
*
**Description: 声明一个车(vehicle)基类,有Run、Stop等成员函数,由此派生出自行车(bicycle)类、汽车(motorcar)类,
                从 bicycle 和 motorcar 派生出摩托车(motorcycle)类,它们都有Run、Stop等成员函数
               
                观察虚函数的作用

** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :7-8.cpp
** 
*
***************************************************/

#include <iostream>
using namespace std;

class Vehicl{
public:
    int MaxSpeed;
    int Weight;
    virtual void Run(){cout << "vehicle run !" << endl; }  // 把基类中的run和stop设置为虚函数,通过vehicle的指针就可以访问派生对象的 run 和 stop 
    virtual void Stop(){cout << " vehicle stop ! " << endl;}
    //void Run(){cout << "vehicle run !" << endl; }    // 如果vehicle类中的 run 和 stop 为普通的成员函数,通过基类vehicle 的指针就不能访问派生类对象的 run 和 stop 
    //void Stop(){cout << " vehicle stop ! " << endl;}  

};

class Bicycle: virtual public Vehicl{
public: 
    int Height;
    void Run(){
        cout << "Bicycle run !" << endl;
    }
    void Stop(){
        cout << " Bicycle stop ! " << endl;
    }

};
class Motorcar: virtual public Vehicl{
public: 
    int SeatNum;
    void Run(){
        cout << "Motorcar run !" << endl;
    }
    void Stop(){
        cout << " Motorcar stop ! " << endl;
    }

};

class Motorcycle: public Motorcar,public Bicycle{
public: 
    void Run(){
        cout << "Motorcycle run !" << endl;
    }
    void Stop(){
        cout << " Motorcycle stop ! " << endl;
    }

};

int main(){
    Vehicl v;
    v.Run();
    v.Stop();
    Bicycle b;
    b.Run();
    b.Stop();
    Motorcar m;
    m.Run();
    m.Stop();
    Motorcycle mc;
    mc.Run();
    mc.Stop();
    Vehicl* vp = &v;   
    /* 如果vehicle类中的 run 和 stop 为普通的成员函数,
    通过基类vehicle 的指针就不能访问派生类对象的 run 和 stop 
    (设置为虚函数就可以) */ 
    
    //想要通过基类的指针和引用访问派生类对象的成员,就要使用虚函数
    vp->Run();
    vp->Stop();
    vp = &b;
    vp->Run();
    vp->Stop();
    vp = &m;
    vp->Run();
    vp->Stop();
    vp = &mc;
    vp->Run();
    vp->Stop();

    system("pause");
    return 0;
}

  • 示例9:
/*************************************************
*
**Description: 综合实例 -- 银行账户 改进
**              :尝试将多个不同类的账户(SavingsAccount 或 CreditAccount)放在一个统一类型的数组中
                  利用循环语句来操作它的deposit、withdraw 或者 settle 函数
                  -(类的设计与完善): 将 show 函数声明为 虚函数;
                  - 使用运算符重载,修改 Date 类等待
                (完整代码仍然为 6 个文件)
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :7-9.cpp
** 
*
***************************************************/

//main.cpp
#include "account.h"
#include <iostream>
using namespace std;

int main() {
	Date date(2008, 11, 1);	//起始日期
	//建立几个账户
	SavingsAccount sa1(date, "S3755217", 0.015);
	SavingsAccount sa2(date, "02342342", 0.015);
	CreditAccount ca(date, "C5392394", 10000, 0.0005, 50);
	Account *accounts[] = { &sa1, &sa2, &ca };
	const int n = sizeof(accounts) / sizeof(Account*);	//账户总数

	cout << "(d)deposit (w)withdraw (s)show (c)change day (n)next month (e)exit" << endl;
	char cmd;
	do {
		//显示日期和总金额
		date.show();
		cout << "\tTotal: " << Account::getTotal() << "\tcommand> ";

		int index, day;
		double amount;
		string desc;

		cin >> cmd;
		switch (cmd) {
		case 'd':	//存入现金
			cin >> index >> amount;
			getline(cin, desc);
			accounts[index]->deposit(date, amount, desc);
			break;
		case 'w':	//取出现金
			cin >> index >> amount;
			getline(cin, desc);
			accounts[index]->withdraw(date, amount, desc);
			break;
		case 's':	//查询各账户信息
			for (int i = 0; i < n; i++) {
				cout << "[" << i << "] ";
				accounts[i]->show();
				cout << endl;
			}
			break;
		case 'c':	//改变日期
			cin >> day;
			if (day < date.getDay())
				cout << "You cannot specify a previous day";
			else if (day > date.getMaxDay())
				cout << "Invalid day";
			else
				date = Date(date.getYear(), date.getMonth(), day);
			break;
		case 'n':	//进入下个月
			if (date.getMonth() == 12)
				date = Date(date.getYear() + 1, 1, 1);
			else
				date = Date(date.getYear(), date.getMonth() + 1, 1);
			for (int i = 0; i < n; i++)
				accounts[i]->settle(date);
			break;
		}
	} while (cmd != 'e');
	
	//system("pause");
	return 0;
}





//account.h
#ifndef __ACCOUNT_H__
#define __ACCOUNT_H__
#include "date.h"
#include "accumulator.h"
#include <string>

class Account { //账户类
private:
	std::string id;	//帐号
	double balance;	//余额
	static double total; //所有账户的总金额
protected:
	//供派生类调用的构造函数,id为账户
	Account(const Date &date, const std::string &id);
	//记录一笔帐,date为日期,amount为金额,desc为说明
	void record(const Date &date, double amount, const std::string &desc);
	//报告错误信息
	void error(const std::string &msg) const;
public:
	const std::string &getId() const { return id; }
	double getBalance() const { return balance; }
	static double getTotal() { return total; }
	//存入现金,date为日期,amount为金额,desc为款项说明
	virtual void deposit(const Date &date, double amount, const std::string &desc) = 0;
	//取出现金,date为日期,amount为金额,desc为款项说明
	virtual void withdraw(const Date &date, double amount, const std::string &desc) = 0;
	//结算(计算利息、年费等),每月结算一次,date为结算日期
	virtual void settle(const Date &date) = 0;
	//显示账户信息
	virtual void show() const;
};

class SavingsAccount : public Account { //储蓄账户类
private:
	Accumulator acc;	//辅助计算利息的累加器
	double rate;		//存款的年利率
public:
	//构造函数
	SavingsAccount(const Date &date, const std::string &id, double rate);
	double getRate() const { return rate; }
	virtual void deposit(const Date &date, double amount, const std::string &desc);
	virtual void withdraw(const Date &date, double amount, const std::string &desc);
	virtual void settle(const Date &date);
};

class CreditAccount : public Account { //信用账户类
private:
	Accumulator acc;	//辅助计算利息的累加器
	double credit;		//信用额度
	double rate;		//欠款的日利率
	double fee;			//信用卡年费

	double getDebt() const {	//获得欠款额
		double balance = getBalance();
		return (balance < 0 ? balance : 0);
	}
public:
	//构造函数
	CreditAccount(const Date &date, const std::string &id, double credit, double rate, double fee);
	double getCredit() const { return credit; }
	double getRate() const { return rate; }
	double getFee() const { return fee; }
	double getAvailableCredit() const {	//获得可用信用
		if (getBalance() < 0) 
			return credit + getBalance();
		else
			return credit;
	}
	virtual void deposit(const Date &date, double amount, const std::string &desc);
	virtual void withdraw(const Date &date, double amount, const std::string &desc);
	virtual void settle(const Date &date);
	virtual void show() const;
};

#endif //__ACCOUNT_H__





//account.cpp
#include "account.h"
#include <cmath>
#include <iostream>
using namespace std;

double Account::total = 0;

//Account类的实现
Account::Account(const Date &date, const string &id)
	: id(id), balance(0) {
	date.show();
	cout << "\t#" << id << " created" << endl;
}

void Account::record(const Date &date, double amount, const string &desc) {
	amount = floor(amount * 100 + 0.5) / 100;	//保留小数点后两位
	balance += amount;
	total += amount;
	date.show();
	cout << "\t#" << id << "\t" << amount << "\t" << balance << "\t" << desc << endl;
}

void Account::show() const {
	cout << id << "\tBalance: " << balance;
}

void Account::error(const string &msg) const {
	cout << "Error(#" << id << "): " << msg << endl;
}

//SavingsAccount类相关成员函数的实现
SavingsAccount::SavingsAccount(const Date &date, const string &id, double rate)
	: Account(date, id), rate(rate), acc(date, 0) { }

void SavingsAccount::deposit(const Date &date, double amount, const string &desc) {
	record(date, amount, desc);
	acc.change(date, getBalance());
}

void SavingsAccount::withdraw(const Date &date, double amount, const string &desc) {
	if (amount > getBalance()) {
		error("not enough money");
	} else {
		record(date, -amount, desc);
		acc.change(date, getBalance());
	}
}

void SavingsAccount::settle(const Date &date) {
	if (date.getMonth() == 1) {	//每年的一月计算一次利息
		double interest = acc.getSum(date) * rate
			/ (date - Date(date.getYear() - 1, 1, 1));
		if (interest != 0)
			record(date, interest, "interest");
		acc.reset(date, getBalance());
	}
}

//CreditAccount类相关成员函数的实现
CreditAccount::CreditAccount(const Date& date, const string& id, double credit, double rate, double fee)
	: Account(date, id), credit(credit), rate(rate), fee(fee), acc(date, 0) { }

void CreditAccount::deposit(const Date &date, double amount, const string &desc) {
	record(date, amount, desc);
	acc.change(date, getDebt());
}

void CreditAccount::withdraw(const Date &date, double amount, const string &desc) {
	if (amount - getBalance() > credit) {
		error("not enough credit");
	} else {
		record(date, -amount, desc);
		acc.change(date, getDebt());
	}
}

void CreditAccount::settle(const Date &date) {
	double interest = acc.getSum(date) * rate;
	if (interest != 0)
		record(date, interest, "interest");
	if (date.getMonth() == 1)
		record(date, -fee, "annual fee");
	acc.reset(date, getDebt());
}

void CreditAccount::show() const {
	Account::show();
	cout << "\tAvailable credit:" << getAvailableCredit();
}






//accumulator.h
#ifndef __ACCUMULATOR_H__
#define __ACCUMULATOR_H__
#include "date.h"

class Accumulator {	//将某个数值按日累加
private:
	Date lastDate;	//上次变更数值的时期
	double value;	//数值的当前值
	double sum;		//数值按日累加之和
public:
	//构造函数,date为开始累加的日期,value为初始值
	Accumulator(const Date &date, double value)
		: lastDate(date), value(value), sum(0) { }

	//获得到日期date的累加结果
	double getSum(const Date &date) const {
		return sum + value * (date - lastDate);
	}

	//在date将数值变更为value
	void change(const Date &date, double value) {
		sum = getSum(date);
		lastDate = date;
		this->value = value;
	}

	//初始化,将日期变为date,数值变为value,累加器清零
	void reset(const Date &date, double value) {
		lastDate = date;
		this->value = value;
		sum = 0;
	}
};

#endif //__ACCUMULATOR_H__








//date.h
#ifndef __DATE_H__
#define __DATE_H__

class Date {	//日期类
private:
	int year;		//年
	int month;		//月
	int day;		//日
	int totalDays;	//该日期是从公元元年1月1日开始的第几天

public:
	Date(int year, int month, int day);	//用年、月、日构造日期
	int getYear() const { return year; }
	int getMonth() const { return month; }
	int getDay() const { return day; }
	int getMaxDay() const;		//获得当月有多少天
	bool isLeapYear() const {	//判断当年是否为闰年
		return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
	}
	void show() const;			//输出当前日期
	//计算两个日期之间差多少天	
	int operator - (const Date& date) const {
		return totalDays - date.totalDays;
	}
};

#endif //__DATE_H__





//date.cpp
#include "date.h"
#include <iostream>
#include <cstdlib>
using namespace std;

namespace {	//namespace使下面的定义只在当前文件中有效
	//存储平年中某个月1日之前有多少天,为便于getMaxDay函数的实现,该数组多出一项
	const int 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)
		return 29;
	else
		return DAYS_BEFORE_MONTH[month]- DAYS_BEFORE_MONTH[month - 1];
}

void Date::show() const {
	cout << getYear() << "-" << getMonth() << "-" << getDay();
}




版权声明:本文为Kefenggewu_原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。