实验5 继承和多态

3.

pets.hpp

#pragma once

#include<iostream>
#include<string>

using namespace std;

class MachinePets {
public:
    MachinePets(const string s);
    virtual string talk() const = 0;
    string get_nickname();
private:
    string nickname;
};
MachinePets::MachinePets(const string s):nickname{s}{}
string MachinePets::get_nickname(){
    return nickname;
}
class PetCats :public MachinePets {
public:
    PetCats(const string& s="");
    string talk() const override;
};
PetCats::PetCats(const string& s) :MachinePets{ s } {};
string PetCats::talk() const {
    return "miao wu ~";
}

class PetDogs :public MachinePets {
public:
    PetDogs(const string& s = "");
    string talk() const override;
};
PetDogs::PetDogs(const string& s) :MachinePets{ s } {};
string PetDogs::talk() const {
    return "wang wang ~";
}
pets.hpp

task3.cpp

#include <iostream>
#include <vector>
#include "pets.hpp"

void test() {
    using namespace std;

    vector<MachinePets*> pets;

    pets.push_back(new PetCats("miku"));
    pets.push_back(new PetDogs("da huang"));

    for (auto& ptr : pets)
        cout << ptr->get_nickname() << " says " << ptr->talk() << endl;
}

int main() {
    test();
}
task3.cpp

运行结果截图

4.

film.hpp

#pragma once
 
#include<string>
#include<iostream>
#include<iomanip>

using std::cout;
using std::string;
using std::ostream;
using std::istream;
using std::endl;
using std::setw;
using std::left;

class Film {
public:
    Film(const string& s="", const string& d="", const string& a="", int t = 0);
    friend ostream& operator<<(ostream& out, const Film& film); 
    friend istream& operator>>(istream& in, Film& film);
    int get_year();
private:
    string name;
    string director;
    string country;
    int year;
};

Film::Film(const string& s , const string& d , const string& a, int t ) :name{ s }, director{ d }, country{ a }, year{ t } {

}
int Film::get_year() {
    return year;
}
bool compare_by_year( Film& x1, Film& x2) {
    return x1.get_year() < x2.get_year();
}
istream& operator>>(istream& in,  Film& film) {
    cout << "输入影名:"; in >> film.name;
    cout << "输入导演:"; in >> film.director;
    cout << "输入上映地区:"; in >> film.country;
    cout << "输入上映年份:"; in >> film.year;
    return in;
}

ostream& operator<<(ostream& out, const Film& film) {
    out << left;
    out << setw(15) << "影名:" << film.name << endl
        << setw(15) << "导演:" << film.director << endl
        << setw(15) << "上映地区:" << film.country << endl
        << setw(15) << "上映年份:" << film.year;
    return out;
}
film.hpp

task4.cpp

#include "film.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

void test() {
    using namespace std;

    int n;
    cout << "输入电影数目: ";
    cin >> n;

    cout << "录入" << n << "部影片信息" << endl;
    vector<Film> film_lst;
    for (int i = 0; i < n; ++i) {
        Film f;
        cout << string(20, '-') << "" << i + 1 << "部影片录入" << string(20, '-') << endl;
        cin >> f;
        film_lst.push_back(f);
    }

    // 按发行年份升序排序
    sort(film_lst.begin(), film_lst.end(), compare_by_year);

    cout << string(20, '=') + "电影信息(按发行年份)" + string(20, '=') << endl;
    for (auto& f : film_lst)
        cout << f << endl;
}

int main() {
    test();
}
task4.cpp

运行结果截图

5.

Complex.hpp

#pragma once
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
using std::ostream;
using std::istream;
template<typename T>
class Complex {
public:
    Complex() :real(T()), imag(T()) {}
    Complex(T r, T i) :real(r), imag(i) {}
    Complex(const Complex<T>& other):real(other.real),imag(other.imag){}
    Complex<T>& operator+=(const Complex<T>& other) {
        real += other.real;
        imag += other.imag;
        return *this;
    }
    Complex<T>operator+(const Complex<T>& other)const {
        return Complex<T>(real + other.real, imag + other.imag);
    }
    bool operator==(const Complex<T>& other)const {
        return real == other.real && imag == other.imag;
    }
    T get_real() const { return real; }
    T get_imag() const { return imag; }
    void set_real(T r) { real = r; }
    void set_imag(T i) { imag = i; }
private:
    T real;
    T imag;
};

template<typename T>
ostream& operator<<(ostream& os, const Complex<T>& c) {
    os << "(" << c.get_real( ) << "," << c.get_imag() << ")";
    return os;
}

template<typename T>
istream& operator>>(istream& is, Complex<T>& c) {
    
    T r, i;
    is >> r;
    is >> i;
    c.set_real(r);
    c.set_imag(i);
    return is;
}
Com

task5.cpp

#include "Complex.hpp"
#include <iostream>

using std::cin;
using std::cout;
using std::endl;
using std::boolalpha;

void test1() {
    Complex<int> c1(2, -5), c2(c1);

    cout << "c1 = " << c1 << endl;
    cout << "c2 = " << c2 << endl;
    cout << "c1 + c2 = " << c1 + c2 << endl;

    c1 += c2;
    cout << "c1 = " << c1 << endl;
    cout << boolalpha << (c1 == c2) << endl;
}

void test2() {
    Complex<double> c1, c2;
    cout << "Enter c1 and c2: ";
    cin >> c1 >> c2;
    cout << "c1 = " << c1 << endl;
    cout << "c2 = " << c2 << endl;

    cout << "c1.real = " << c1.get_real() << endl;
    cout << "c1.imag = " << c1.get_imag() << endl;
}

int main() {
    cout << "自定义类模板Complex测试1: " << endl;
    test1();

    cout << endl;

    cout << "自定义类模板Complex测试2: " << endl;
    test2();
}
task5.cpp

运行结果截图

6.

 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);
    void record(const Date& date, double amount, const std::string& desc);//记录一笔账,date为日期,amount为金额,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;
    //取出现金
    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; }
    //存入现金
    void deposit(const Date& date, double amount,const std::string &desc);
    //取出现金
    void withdraw(const Date& date, double amount, const std::string& desc);
    void settle(const Date& date);//结算利息,每年1月1日调用一次该函数
};
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;
    }
    //存入现金
    void deposit(const Date& date, double amount, const std::string& desc);
    //取出现金
    void withdraw(const Date& date, double amount, const std::string& desc);
    void settle(const Date& date);
    void show()const;
};
#endif
account.h

accumulator.h

#ifndef __ACCUMULATOR_H__
#define __ACCUMULATOR_H__
#include"date.h"
class Accumulator {//将某a个数值按日累加
private:
    Date lastDate;//上次变更数值的时期
    double value;//数值的当前值
    double sum;//数值按日累加之和
public:
    double getSum(const Date &date)const {
        return sum + value * (date - lastDate);
    }
    Accumulator(const Date &date,double value):lastDate(date),value(value),sum(0){}//构造函数,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;//初始化,将日期变为date,数值变为value,累加器清零
    }
};
#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.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) {//每年的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, "annial fee");
    acc.reset(date, getDebt());
}
void CreditAccount::show()const {
    Account::show();
    cout << "\tAvailbale credit:" << getAvailableCredit();
}
account.cpp

date.cpp

#include"date.h"
#include<iostream>
#include<cstdlib>
using namespace std;
namespace {
    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 = year * 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();
}
date.cpp

task6.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');
    return 0;
}
task6.cpp

运行结果截图

在基类Account中将账户的公共操作皆申明为虚函数,因此可以通过基类的指针来执行各种操作,因而各种类型的账户对象都可以通过一个基类指针的数组来访问。不能动态增加账户。

posted @ 2024-12-04 21:13  226都有人用?  阅读(7)  评论(0编辑  收藏  举报