实验5 继承和多态
任务3
pets.hpp
1 #include<iostream> 2 #include<string> 3 4 using std::cout; 5 using std::endl; 6 using std::string; 7 8 class MachinePets { 9 public: 10 MachinePets(const string &s =""); 11 12 public: 13 string get_nickname() const; 14 virtual string talk() const =0; 15 private: 16 string nickname; 17 }; 18 19 MachinePets::MachinePets(const string &s):nickname(s){ 20 } 21 22 string MachinePets::get_nickname() const{ 23 return nickname; 24 } 25 26 class PetCats:public MachinePets { 27 public: 28 PetCats(const string &s =""); 29 30 public: 31 string talk() const override; 32 33 }; 34 35 PetCats::PetCats(const string &s):MachinePets(s){ 36 } 37 38 string PetCats::talk() const { 39 string jiao="miao"; 40 return jiao; 41 } 42 43 class PetDogs:public MachinePets { 44 public: 45 PetDogs(const string &s =""); 46 47 public: 48 string talk() const override; 49 50 }; 51 52 PetDogs::PetDogs(const string &s):MachinePets(s){ 53 } 54 55 string PetDogs::talk() const { 56 string jiao="wang"; 57 return jiao; 58 }
task3.cpp
1 #include <iostream> 2 #include <vector> 3 #include "pets.hpp" 4 5 void test() { 6 using namespace std; 7 8 vector<MachinePets *> pets; 9 10 pets.push_back(new PetCats("miku")); 11 pets.push_back(new PetDogs("da huang")); 12 13 for(auto &ptr: pets) 14 cout <<ptr->get_nickname() << " says " << ptr->talk() << endl; 15 } 16 17 int main() { 18 test(); 19 }
运行结果
任务4
film.hpp
1 #include<iostream> 2 #include<string> 3 #include<iomanip> 4 5 using std::string; 6 using std::ostream; 7 using std::istream; 8 using std::endl; 9 using std::setw; 10 using std::left; 11 12 class Film{ 13 public: 14 Film(const string &name="",const string &director="",const string ®ion="",const int &year=0); 15 friend istream& operator>>(istream &in,Film &film); 16 friend ostream& operator<<(ostream &out,const Film &film); 17 int get_year() const; 18 private: 19 string name; 20 string director; 21 string region; 22 int year; 23 }; 24 25 Film::Film(const string &name,const string &director,const string ®ion,const int &year){ 26 } 27 28 istream& operator>>(istream &in,Film &film){ 29 in>>film.name>>film.director>>film.region>>film.year; 30 return in; 31 } 32 33 ostream& operator<<(ostream &out,const Film &film){ 34 out<<left; 35 out<<setw(15)<<film.name<<setw(15)<<film.director<<setw(15)<<film.region<<setw(15)<<film.year<<endl; 36 return out; 37 } 38 39 int Film::get_year() const{ 40 return year; 41 } 42 43 bool compare_by_year(const Film &f1,const Film &f2){ 44 return f1.get_year()>f2.get_year(); 45 }
task4.cpp
1 #include "film.hpp" 2 #include <iostream> 3 #include <string> 4 #include <vector> 5 #include <algorithm> 6 7 void test() { 8 using namespace std; 9 10 int n; 11 cout << "输入电影数目: "; 12 cin >> n; 13 14 cout << "录入" << n << "部影片信息" << endl; 15 vector<Film> film_lst; 16 for(int i = 0; i < n; ++i) { 17 Film f; 18 cout << string(20, '-') << "第" << i+1 << "部影片录入" << string(20, '-') << endl; 19 cin >> f; 20 film_lst.push_back(f); 21 } 22 23 // 按发行年份升序排序 24 sort(film_lst.begin(), film_lst.end(), compare_by_year); 25 26 cout << string(20, '=') + "电影信息(按发行年份)" + string(20, '=')<< endl; 27 for(auto &f: film_lst) 28 cout << f << endl; 29 } 30 31 int main() { 32 test(); 33 }
运行结果
任务5
Complex.hpp
1 #ifndef COMPLEX_HPP 2 #define COMPLEX_HPP 3 4 #include <iostream> 5 6 using std::istream; 7 using std::ostream; 8 9 template <typename T> 10 class Complex { 11 private: 12 T real; 13 T imag; 14 15 public: 16 // 默认 17 Complex(T r = 0, T i = 0) : real(r), imag(i) {} 18 19 // 复制 20 Complex(const Complex<T>& other) : real(other.real), imag(other.imag) {} 21 22 // +重载 23 Complex<T> operator+(const Complex<T>& other) const { 24 return Complex<T>(real + other.real, imag + other.imag); 25 } 26 27 // +=重载 28 Complex<T>& operator+=(const Complex<T>& other) { 29 real += other.real; 30 imag += other.imag; 31 return *this; 32 } 33 34 // ==重载 35 bool operator==(const Complex<T>& other) const { 36 return real == other.real && imag == other.imag; 37 } 38 39 // 得到实部 40 T get_real() const { 41 return real; 42 } 43 44 // 得到虚部 45 T get_imag() const { 46 return imag; 47 } 48 49 // 输出重载 50 friend ostream& operator<<(ostream& os, const Complex<T>& c) { 51 os << c.real; 52 if (c.imag >= 0) { 53 os << " + " << c.imag << "i"; 54 } else { 55 os << " - " << -c.imag << "i"; 56 } 57 return os; 58 } 59 60 // 输入重载 61 friend istream& operator>>(istream& is, Complex<T>& c) { 62 is >> c.real >>c.imag; 63 return is; 64 } 65 }; 66 67 #endif
task5.cpp
1 #include "Complex.hpp" 2 #include <iostream> 3 4 using std::cin; 5 using std::cout; 6 using std::endl; 7 using std::boolalpha; 8 9 void test1() { 10 Complex<int> c1(2, -5), c2(c1); 11 12 cout << "c1 = " << c1 << endl; 13 cout << "c2 = " << c2 << endl; 14 cout << "c1 + c2 = " << c1 + c2 << endl; 15 16 c1 += c2; 17 cout << "c1 = " << c1 << endl; 18 cout << boolalpha << (c1 == c2) << endl; 19 } 20 21 void test2() { 22 Complex<double> c1, c2; 23 cout << "Enter c1 and c2: "; 24 cin >> c1 >> c2; 25 cout << "c1 = " << c1 << endl; 26 cout << "c2 = " << c2 << endl; 27 28 cout << "c1.real = " << c1.get_real() << endl; 29 cout << "c1.imag = " << c1.get_imag() << endl; 30 } 31 32 int main() { 33 cout << "自定义类模板Complex测试1: " << endl; 34 test1(); 35 36 cout << endl; 37 38 cout << "自定义类模板Complex测试2: " << endl; 39 test2(); 40 }
运行结果
任务6
8_8.cpp
1 #include"account.h"" 2 #include<iostream> 3 using namespace std; 4 int main() 5 { 6 Date date(2008,11,1); 7 SavingsAccount sa1(date,"s3755271",0.015); 8 SavingsAccount sa2(date,"02342342",0.015); 9 CreditAccount ca(date,"C5392394",10000,0.0005,50); 10 Account *accounts[]={&sa1,&sa2,&ca}; 11 const int n=sizeof(accounts)/sizeof(Account *); 12 cout<<"(d)deposit (w)withdraw (s) show (c) change day (n) next month (e) exit"<<endl; 13 char cmd; 14 do{ 15 date.show(); 16 cout<<"\tTotal:"<<Account::getTotal()<<"\tcommand>"; 17 int index,day; 18 double amount; 19 string desc; 20 cin>>cmd; 21 switch(cmd){ 22 case 'd': 23 cin>>index>>amount; 24 getline(cin,desc); 25 accounts[index]->deposit(date,amount,desc); 26 break; 27 case 'w': 28 cin>>index>>amount; 29 getline(cin,desc); 30 accounts[index]->withdraw(date,amount,desc); 31 break; 32 case 's': 33 for(int i=0;i<n;i++) 34 { 35 cout<<"["<<i<<"]"; 36 accounts[i]->show(); 37 cout<<endl; 38 } 39 break; 40 case 'c': 41 cin>>day; 42 if(day<date.getDay()) 43 cout<<"You cannot specify a previous day"; 44 else if(day>date.getDay()) 45 cout<<"Invalid day"; 46 else 47 date=Date(date.getYear(),date.getMonth(),day); 48 break; 49 case 'n': 50 if(date.getMonth()==12) 51 date=Date(date.getYear()+1,1,1); 52 else 53 date=Date(date.getYear(),date.getMonth()+1,1); 54 for(int i=0;i<n;i++) 55 { 56 accounts[i]->settle(date); 57 } 58 break; 59 } 60 }while(cmd!='e'); 61 return 0; 62 }
date.h
1 #ifndef __DATE_H__ 2 #define __DATE_H__ 3 class Date{ 4 private: 5 int year; 6 int month; 7 int day; 8 int totalDays; 9 public: 10 Date(int year,int month,int day); 11 int getYear() const {return year;} 12 int getMonth() const {return month;} 13 int getDay() const {return day;} 14 int getMaxDay() const; 15 bool isLeapYear() const { 16 return year%4==0 && year%100 !=0 ||year%400==0; 17 } 18 void show() const; 19 20 int operator-(const Date& date) const { 21 return totalDays-date.totalDays; 22 } 23 }; 24 #endif //__DATE_H__
date.cpp
1 #include "date.h" 2 #include <iostream> 3 #include <cstdlib> 4 using namespace std; 5 namespace { 6 const int DAYS_BEFORE_MONTH[]={0,31,59,90,120,151,181,212,243,273,304,334,365}; 7 } 8 Date::Date(int year,int month,int day):year(year),month(month),day(day) { 9 if(day<=0||day>getMaxDay()) { 10 cout<<"Invalid date:"; 11 show(); 12 cout<<endl; 13 exit(1); 14 } 15 int years=year-1; 16 totalDays = years *365+years/4-years/100+years/400+DAYS_BEFORE_MONTH[month-1]+day; 17 if(isLeapYear()&&month>2) totalDays++; 18 } 19 20 int Date::getMaxDay() const { 21 if(isLeapYear()&&month==2) 22 return 29; 23 else 24 return DAYS_BEFORE_MONTH[month]-DAYS_BEFORE_MONTH[month-1]; 25 } 26 27 void Date::show() const { 28 cout<<getYear()<<"-"<<getMonth()<<"-"<<getDay(); 29 }
account.h
1 #ifndef ACCOUNT H 2 #define ACCOUNT H 3 #include"date.h" 4 #include"accumulator.h" 5 #include<string> 6 class Account { 7 private: 8 std::string id; 9 double balance; 10 static double total; 11 protected: 12 Account(const Date& date, const std::string& id); 13 void record(const Date& date, double amount, const std::string& desc); 14 void error(const std::string& msg)const; 15 public: 16 const std::string& getId()const { return id; } 17 double getBalance()const { return balance; } 18 static double getTotal() { return total; } 19 20 virtual void deposit(const Date& date, double amount, const std::string& desc)=0; 21 virtual void withdraw(const Date& date, double amount, const std::string& desc)=0; 22 virtual void settle(const Date& date)=0; 23 24 virtual void show()const; 25 }; 26 class SavingsAccount :public Account { 27 private: 28 Accumulator acc; 29 double rate; 30 public: 31 SavingsAccount(const Date& date, const std::string& id, double rate); 32 double getRate()const { return rate; } 33 void deposit(const Date& date, double amount, const std::string& desc); 34 void withdraw(const Date& date, double amount, const std::string& desc); 35 void settle(const Date& date); 36 37 }; 38 class CreditAccount :public Account { 39 private: 40 Accumulator acc; 41 double credit; 42 double rate; 43 double fee; 44 double getDebt()const { 45 double balance = getBalance(); 46 return (balance < 0 ? balance : 0); 47 } 48 public: 49 CreditAccount(const Date& date, const std::string& id, double credit, double rate, double fee); 50 double getCredit()const { return credit; } 51 double getRate()const { return rate; } 52 double getAvailableCredit()const { 53 if (getBalance() < 0) 54 return credit + getBalance(); 55 else 56 return credit; 57 } 58 void deposit(const Date& date, double amount, const std::string& desc); 59 void withdraw(const Date& date, double amount, const std::string& desc); 60 void settle(const Date& date); 61 void show()const; 62 }; 63 #endif//ACCOUNT H
account.cpp
1 #include"account.h" 2 #include<cmath> 3 #include<iostream> 4 using namespace std; 5 double Account::total = 0; 6 7 Account::Account(const Date& date, const string& id) :id{ id }, balance{ 0 } { 8 date.show(); cout << "\t#" << id << "created" << endl; 9 } 10 11 12 void Account::record(const Date& date, double amount, const string& desc) { 13 amount = floor(amount * 100 + 0.5) / 100; 14 balance += amount; 15 total += amount; 16 date.show(); 17 cout << "\t#" << id << "\t" << amount << "\t" << balance << "\t" << desc << endl; 18 } 19 20 void Account::show()const { cout << id << "\tBalance:" << balance; } 21 void Account::error(const string& msg)const { 22 cout << "Error(#" << id << "):" << msg << endl; 23 } 24 25 SavingsAccount::SavingsAccount(const Date& date, const string& id, double rate) :Account(date, id), rate(rate), acc(date, 0) {} 26 27 void SavingsAccount::deposit(const Date& date, double amount, const string& desc) { 28 record(date, amount, desc); 29 acc.change(date, getBalance()); 30 } 31 32 void SavingsAccount::withdraw(const Date& date, double amount, const string& desc) { 33 if (amount > getBalance()) { 34 error("not enough money"); 35 } 36 else { 37 record(date, -amount, desc); 38 acc.change(date, getBalance()); 39 } 40 } 41 42 void SavingsAccount::settle(const Date& date) { 43 double interest = acc.getSum(date) * rate / (date-Date(date.getYear() - 1, 1, 1)); 44 if (interest != 0)record(date, interest, "interest"); 45 acc.reset(date, getBalance()); 46 } 47 48 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) {} 49 50 void CreditAccount::deposit(const Date& date, double amount, const string& desc) { 51 record(date, amount, desc); 52 acc.change(date, getDebt()); 53 } 54 55 void CreditAccount::withdraw(const Date& date, double amount, const string& desc) { 56 if (amount - getBalance() > credit) { 57 error("not enough credit"); 58 } 59 else { 60 record(date, -amount, desc); 61 acc.change(date, getDebt()); 62 } 63 } 64 65 void CreditAccount::settle(const Date& date) { 66 double interest = acc.getSum(date) * rate; 67 if (interest != 0)record(date, interest, "interest"); 68 if (date.getMonth() == 1) 69 record(date, -fee, "annual fee"); 70 acc.reset(date, getDebt()); 71 } 72 73 void CreditAccount::show()const { 74 Account::show(); 75 cout << "\tAvailable credit:" << getAvailableCredit(); 76 }
accumulator.h
1 #ifndef ACCUMULATOR H 2 #define ACCUMULATOR H 3 #include"date.h" 4 class Accumulator { 5 private: 6 Date lastDate; 7 double value; 8 double sum; 9 public: 10 Accumulator(const Date& date, double value) :lastDate(date), value(value), sum{ 0 } { 11 } 12 13 double getSum(const Date& date)const { 14 return sum + value * (date-lastDate); 15 } 16 17 void change(const Date& date, double value) { 18 sum = getSum(date); 19 lastDate = date; this->value = value; 20 } 21 22 void reset(const Date& date, double value) { 23 lastDate = date; this->value = value; sum = 0; 24 } 25 }; 26 #endif//ACCUMULATOR H
运行结果
改进:重载了-运算符,使书写更加简便易懂;使用虚函数,实现运行时多态,使程序更安全;
改善:用户的输入窗口有待美化,使输入更加便捷直观;数据的展示方式可以采用更整齐的排版;数据的存储和访问方式可以改进以提高运行效率。