实验5
实验任务1:
publisher.hpp:
1 #pragma once 2 3 #include<iostream> 4 #include<string> 5 6 using std::cout; 7 using std::endl; 8 using std::string; 9 10 class Publisher{ 11 public: 12 Publisher(const string &s = ""); 13 14 public: 15 virtual void publish() const = 0; 16 virtual void use() const = 0; 17 18 protected: 19 string name; 20 }; 21 22 Publisher::Publisher(const string &s):name{s}{ 23 } 24 25 class Book:public Publisher{ 26 public: 27 Book(const string &s = "",const string &a = ""); 28 29 public: 30 void publish() const override; 31 void use() const override; 32 33 private: 34 string author; 35 }; 36 37 Book::Book(const string &s,const string &a):Publisher{s},author{a}{ 38 } 39 40 void Book::publish() const { 41 cout << "Publishing book: 《" << name << "》by" << author << endl; 42 } 43 44 void Book::use() const { 45 cout << "Reading book: " << name << "by" << author << endl; 46 } 47 48 class Film:public Publisher { 49 public: 50 Film(const string &s = " ",const string &d = " "); 51 52 public: 53 void publish() const override; 54 void use() const override; 55 56 private: 57 string director; 58 }; 59 60 Film::Film(const string &s,const string &d):Publisher{s},director{d}{ 61 } 62 63 void Film::publish() const { 64 cout << "Publishing film:<" << name << "> directored by " << director << endl; 65 } 66 67 void Film::use() const { 68 cout << "watching film: " << name << "directored by " << director << endl; 69 } 70 71 class Music:public Publisher { 72 public: 73 Music(const string &s = "",const string &a = ""); 74 75 public: 76 void publish() const override; 77 void use() const override; 78 79 private: 80 string artist; 81 }; 82 83 Music::Music(const string &s,const string &a):Publisher{s},artist{a}{ 84 } 85 86 void Music::publish() const { 87 cout << "Publishing music <" << name << "> by " << artist << endl; 88 } 89 90 void Music::use() const { 91 cout << "Listening to music: " << name << " by " << artist << endl; 92 }
task1.cpp:
1 #include"publisher.hpp" 2 #include<vector> 3 #include<typeinfo> 4 5 using std::vector; 6 7 void test(){ 8 vector<Publisher *> v; 9 10 v.push_back(new Book("Harry Potter","J.K.Rowling")); 11 v.push_back(new Film("The Godfather","Franci Ford Coppola")); 12 v.push_back(new Music("Blowing in the wind","Bob Dylan")); 13 14 for(auto &ptr: v){ 15 cout << "pointer type: " << typeid(ptr).name() << endl; 16 cout << "RTTI type: " << typeid(*ptr).name() << endl; 17 ptr->publish(); 18 ptr->use(); 19 cout << endl; 20 } 21 } 22 23 int main(){ 24 test(); 25 }
实验任务2:
book.hpp:
1 #pragma once 2 3 #include <string> 4 #include <iostream> 5 #include <iomanip> 6 7 using std::string; 8 using std::ostream; 9 using std::endl; 10 using std::setw; 11 using std::left; 12 13 class Book { 14 public: 15 Book(const string &name,const string &author,const string &translator,const string &isbn,float price); 16 friend ostream& operator<<(ostream &out,const Book &book); 17 18 private: 19 string name; 20 string author; 21 string translator; 22 string isbn; 23 float price; 24 }; 25 26 Book::Book(const string &name,const string &author,const string &translator,const string &isbn,float price){ 27 this->name = name; 28 this->author = author; 29 this->translator = translator; 30 this->isbn = isbn; 31 this->price = price; 32 } 33 34 ostream& operator<<(ostream &out,const Book &book){ 35 out << left; 36 out << setw(15) << "书名: " << book.name << endl 37 << setw(15) << "作者: " << book.author << endl 38 << setw(15) << "译者: " << book.translator << endl 39 << setw(15) << "定价: " << book.price; 40 41 return out; 42 }
booksale.hpp:
1 #pragma once 2 3 #include "book.hpp" 4 #include <iostream> 5 #include <string> 6 #include <iomanip> 7 8 using std::string; 9 using std::cout; 10 using std::endl; 11 using std::setw; 12 13 class BookSale { 14 public: 15 BookSale(const Book &b,float price,int amount); 16 int get_amount() const; 17 friend ostream& operator<<(ostream &out,const BookSale &item); 18 19 private: 20 Book rb; 21 float sales_price; 22 int sales_amount; 23 float revenue; 24 }; 25 26 BookSale::BookSale(const Book &b,float price,int amount):rb{b},sales_price{price},sales_amount{amount}{ 27 revenue = sales_amount * sales_price; 28 } 29 30 int BookSale::get_amount() const { 31 return sales_amount; 32 } 33 34 ostream& operator<<(ostream &out,const BookSale &item){ 35 out << left; 36 out << item.rb << endl 37 << setw(15) << "售价: " << item.sales_price << endl 38 << setw(15) << "销售数量: " << item.sales_amount << endl 39 << setw(15) << "营收: " << item.revenue; 40 41 return out; 42 }
task2.cpp:
1 #include "booksale.hpp" 2 #include <iostream> 3 #include <string> 4 #include <vector> 5 #include <algorithm> 6 7 bool compare_by_amount(const BookSale &x1,const BookSale &x2){ 8 return x1.get_amount() > x2.get_amount(); 9 } 10 11 void test(){ 12 using namespace std; 13 14 vector<BookSale> sales_lst; 15 16 int books_number; 17 cout << "录入图书数量: "; 18 cin >> books_number; 19 cout << "录入图书销售记录" << endl; 20 for(int i = 0;i < books_number;++i){ 21 string name,author,translator,isbn; 22 float price; 23 cout << string(20,'-') << "第" << i+1 << "本图书信息录入" << string(20,'-') << endl; 24 cout << "录入书名: ";cin >> name; 25 cout << "录入作者: ";cin >> author; 26 cout << "录入译者: ";cin >> translator; 27 cout << "录入isbn: ";cin >> isbn; 28 cout << "录入定价: ";cin >> price; 29 30 Book book(name,author,translator,isbn,price); 31 32 float sales_price; 33 int sales_amount; 34 35 cout << "录入售价: ";cin >> sales_price; 36 cout << "录入销售数量: ";cin >> sales_amount; 37 38 BookSale record(book,sales_price,sales_amount); 39 sales_lst.push_back(record); 40 } 41 42 sort(sales_lst.begin(),sales_lst.end(),compare_by_amount); 43 44 cout << string(20,'=') << "图书销售统计" << string(20,'=') << endl; 45 for(auto &t:sales_lst){ 46 cout << t << endl; 47 cout << string(40,'-') << endl; 48 } 49 } 50 51 int main(){ 52 test(); 53 }
实验任务3:
pets.hpp:
1 #pragma once 2 3 #include <iostream> 4 #include <string> 5 6 using std::cout; 7 using std::endl; 8 using std::string; 9 10 class MachinePets{ 11 public: 12 MachinePets(const string &s = " "); 13 string get_nickname() const; 14 15 public: 16 virtual string talk() = 0; 17 18 private: 19 string nickname; 20 }; 21 22 MachinePets::MachinePets(const string &s):nickname{s}{ 23 } 24 25 string MachinePets::get_nickname() const{ 26 return nickname; 27 } 28 29 class PetCats:public MachinePets{ 30 public: 31 PetCats(const string &s = " "); 32 33 public: 34 string talk() override; 35 }; 36 37 PetCats::PetCats(const string &s):MachinePets(s){ 38 } 39 40 string PetCats::talk(){ 41 return " miao wu~"; 42 } 43 44 class PetDogs:public MachinePets{ 45 public: 46 PetDogs(const string &s = " "); 47 48 public: 49 string talk() override; 50 }; 51 52 PetDogs::PetDogs(const string &s):MachinePets(s){ 53 } 54 55 string PetDogs::talk(){ 56 return " wang wang~"; 57 }
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 #pragma once 2 3 #include<iostream> 4 #include<string> 5 #include<iomanip> 6 7 using std::string; 8 using std::istream; 9 using std::ostream; 10 using std::cout; 11 using std::setw; 12 using std::left; 13 using std::endl; 14 15 class Film { 16 public: 17 Film(const string &title = " ", const string &director = " ", const string &country = " ", int year = 0); 18 int get_year() const {return year;} 19 20 friend istream& operator >> (istream &in, Film &film); 21 friend ostream& operator << (ostream &out, const Film &film); 22 23 private: 24 string title; 25 string director; 26 string country; 27 int year; 28 }; 29 30 Film::Film(const string &title, const string &director, const string &country, int year){ 31 this->title = title; 32 this->director = director; 33 this->country = country; 34 this->year = year; 35 } 36 37 istream& operator >> (istream &in, Film &film){ 38 cout << "录入片名: "; 39 in >> film.title; 40 cout << "录入导演: "; 41 in >> film.director; 42 cout << "录入制片国家/地区: "; 43 in >> film.country; 44 cout << "录入上映年份: "; 45 in >> film.year; 46 return in; 47 } 48 49 ostream& operator << (ostream &out, const Film &film) { 50 out << left; 51 out << film.title 52 << setw(15) << film.director << setw(15) << film.country << setw(15) << film.year; 53 54 return out; 55 } 56 57 bool compare_by_year(const Film &a, const Film &b) { 58 return a.get_year() < b.get_year(); 59 }
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 sort(film_lst.begin(), film_lst.end(), compare_by_year); 24 25 cout << string(20, '=') + "电影信息(按发行年份)" + string(20, '=')<< endl; 26 for(auto &f: film_lst) 27 cout << f << endl; 28 } 29 30 int main() { 31 test(); 32 }
实验任务5:
Complex.hpp:
1 #pragma once 2 3 #include <iostream> 4 #include<vector> 5 6 using namespace std; 7 8 template <typename T> 9 class Complex { 10 public: 11 Complex(T real = 0, T imag = 0) : real(real), imag(imag) {} 12 T get_real() const { return real; } 13 T get_imag() const { return imag; } 14 15 Complex &operator+=(const Complex &other) { 16 real += other.real; 17 imag += other.imag; 18 return *this; 19 } 20 21 Complex operator+(const Complex &other) const { 22 return Complex(real + other.real, imag + other.imag); 23 } 24 25 bool operator==(const Complex &other) const { 26 return (real == other.real) && (imag == other.imag); 27 } 28 29 friend istream &operator>>(istream &in, Complex &c) { 30 in >> c.real; 31 in >> c.imag; 32 return in; 33 } 34 35 friend ostream &operator<<(ostream &out, const Complex &c) { 36 if(c.imag > 0) 37 out << c.real << " + " << c.imag << "i"; 38 else 39 out << c.real << " " << c.imag << "i"; 40 return out; 41 } 42 43 private: 44 T real; 45 T imag; 46 };
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 cout << "c1 = " << c1 << endl; 12 cout << "c2 = " << c2 << endl; 13 cout << "c1 + c2 = " << c1 + c2 << endl; 14 c1 += c2; 15 cout << "c1 = " << c1 << endl; 16 cout << boolalpha << (c1 == c2) << endl; 17 } 18 19 void test2() { 20 Complex<double> c1, c2; 21 cout << "Enter c1 and c2: "; 22 cin >> c1 >> c2; 23 cout << "c1 = " << c1 << endl; 24 cout << "c2 = " << c2 << endl; 25 cout << "c1.real = " << c1.get_real() << endl; 26 cout << "c1.imag = " << c1.get_imag() << endl; 27 } 28 29 int main() { 30 cout << "自定义类模板Complex测试1: " << endl; 31 test1(); 32 cout << endl; 33 cout << "自定义类模板Complex测试2: " << endl; 34 test2(); 35 }
实验任务6:
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 int operator-(const Date& date) const { 20 return totalDays - date.totalDays; 21 } 22 }; 23 #endif //__DATE_H__
date.cpp:
1 #include "date.h" 2 #include <iostream> 3 #include <cstdlib> 4 using namespace std; 5 6 namespace { 7 const int DAYS_BEFORE_MONTH[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; 8 } 9 10 Date::Date(int year, int month, int day) : year(year), month(month), day(day) { 11 if (day <= 0 || day > getMaxDay()) { 12 cout << "Invalid date: "; 13 show(); 14 cout << endl; 15 exit(1); 16 } 17 int years = year - 1; 18 totalDays = years * 365 + years / 4 - years / 100 + years / 400 + DAYS_BEFORE_MONTH[month - 1] + day; 19 if (isLeapYear() && month > 2) totalDays++; 20 } 21 22 int Date::getMaxDay() const { 23 if (isLeapYear() && month == 2) 24 return 29; 25 else return DAYS_BEFORE_MONTH[month] - DAYS_BEFORE_MONTH[month - 1]; 26 } 27 28 void Date::show() const { 29 cout << getYear() << "-" << getMonth() << "-" << getDay(); 30 }
accumulator.h:
1 #ifndef __ACCUMULATOR_H__ 2 #define __ACCUMULATOR_H__ 3 #include "date.h" 4 5 class Accumulator { 6 private: 7 Date lastDate; 8 double value; 9 double sum; 10 11 public: 12 Accumulator(const Date& date, double value) : lastDate(date), value(value), sum{ 0 } {} 13 14 double getSum(const Date& date) const { 15 return sum + value * (date - lastDate); 16 } 17 18 void change(const Date& date, double value) { 19 sum = getSum(date); 20 lastDate = date; 21 this->value = value; 22 } 23 24 void reset(const Date& date, double value) { 25 lastDate = date; 26 this->value = value; 27 sum = 0; 28 } 29 }; 30 #endif //__ACCUMULATOR_H__
account.h:
1 #ifndef __ACCOUNT_H__ 2 #define __ACCOUNT_H__ 3 #include "date.h" 4 #include "accumulator.h" 5 #include <string> 6 using namespace std; 7 8 class Account { 9 private: 10 string id; 11 double balance; 12 static double total; 13 protected: 14 Account(const Date& date, const string& id); 15 void record(const Date& date, double amount, const string& desc); 16 void error(const string& msg) const; 17 public: 18 const string& getId() { return id; } 19 double getBalance() const { return balance; } 20 static double getTotal() { return total; } 21 virtual void deposit(const Date& date, double amount, const string& desc) = 0; 22 virtual void withdraw(const Date& date, double amount, const string& desc) = 0; 23 virtual void settle(const Date& date) = 0; 24 virtual void show() const; 25 }; 26 27 class SavingsAccount : public Account { 28 private: 29 Accumulator acc; 30 double rate; 31 public: 32 SavingsAccount(const Date& date, const string& id, double rate); 33 double getRate() const { return rate; } 34 void deposit(const Date& date, double amount, const string& desc); 35 void withdraw(const Date& date, double amount, const string& desc); 36 void settle(const Date& date); 37 }; 38 39 class CreditAccount : public Account { 40 private: 41 Accumulator acc; 42 double credit; 43 double rate; 44 double fee; 45 double getDebt() const { 46 double balance = getBalance(); 47 return (balance < 0 ? balance : 0); 48 } 49 public: 50 CreditAccount(const Date& date, const string& id, double credit, double rate, double fee); 51 double getCredit() const { return credit; } 52 double getRate() const { return rate; } 53 double getFee() const { return fee; } 54 double getAvailableCredit() const { 55 if (getBalance() < 0) return credit + getBalance(); 56 else return credit; 57 } 58 void deposit(const Date& date, double amount, const string& desc); 59 void withdraw(const Date& date, double amount, const string& desc); 60 void settle(const Date& date); 61 void show() const; 62 }; 63 64 #endif //__ACCOUNT_H__
account.cpp:
1 #include "account.h" 2 #include <cmath> 3 #include<iostream> 4 using namespace std; 5 6 double Account::total = 0; 7 8 Account::Account(const Date& date, const string& id) : id(id), balance(0) { 9 date.show(); 10 cout << "\t#" << id << " created" << endl; 11 } 12 13 void Account::record(const Date& date, double amount, const string& desc) { 14 amount = floor(amount * 100 + 0.5) / 100; 15 balance += amount; 16 total += amount; 17 date.show(); 18 cout << "\t#" << id << "\t" << amount << "\t" << balance << "\t" << desc << endl; 19 } 20 21 void Account::show() const { 22 cout << id << "\tBalance: " << balance; 23 } 24 25 void Account::error(const string& msg) const { 26 cout << "Error (#" << id << "): " << msg << endl; 27 } 28 29 SavingsAccount::SavingsAccount(const Date& date, const string& id, double rate) 30 : Account(date, id), rate(rate), acc(date, 0) {} 31 32 void SavingsAccount::deposit(const Date& date, double amount, const string& desc) { 33 record(date, amount, desc); 34 acc.change(date, getBalance()); 35 } 36 37 void SavingsAccount::withdraw(const Date& date, double amount, const string& desc) { 38 if (amount > getBalance()) { 39 error("not enough money"); 40 } 41 else { 42 record(date, -amount, desc); 43 acc.change(date, getBalance()); 44 } 45 } 46 47 void SavingsAccount::settle(const Date& date) { 48 if(date.getMonth() == 1){ 49 double interest = acc.getSum(date) * rate / (date - Date(date.getYear() - 1, 1, 1)); 50 if (interest != 0) record(date, interest, "interest"); 51 acc.reset(date, getBalance()); 52 } 53 } 54 55 CreditAccount::CreditAccount(const Date& date, const string& id, double credit, double rate, double fee) 56 : Account(date, id), credit(credit), rate(rate), fee(fee), acc(date, 0) {} 57 58 void CreditAccount::deposit(const Date& date, double amount, const string& desc) { 59 record(date, amount, desc); 60 acc.change(date, getDebt()); 61 } 62 63 void CreditAccount::withdraw(const Date& date, double amount, const string& desc) { 64 if (amount - getBalance() > credit) { 65 error("not enough credit"); 66 } 67 else { 68 record(date, -amount, desc); 69 acc.change(date, getDebt()); 70 } 71 } 72 73 void CreditAccount::settle(const Date& date) { 74 double interest = acc.getSum(date) * rate; 75 if (interest != 0) record(date, interest, "interest"); 76 if (date.getMonth() == 1) record(date, -fee, "annual fee"); 77 acc.reset(date, getDebt()); 78 } 79 80 void CreditAccount::show() const { 81 Account::show(); 82 cout << "\tAvailable credit: " << getAvailableCredit(); 83 }
8_8.cpp:
1 #include "account.h" 2 #include<iostream> 3 4 using namespace std; 5 6 int main() { 7 Date date(2008, 11, 1); 8 SavingsAccount sa1(date, "S3755217", 0.015); 9 SavingsAccount sa2(date, "02342342", 0.015); 10 CreditAccount ca(date, "C5392394", 10000, 0.0005, 50); 11 Account* accounts[] = { &sa1, &sa2, &ca }; 12 const int n = sizeof(accounts) / sizeof(Account*); 13 cout << "(d)deposit (w)withdraw (s)show (c)change day (n)next month (e)exit" << endl; 14 char cmd; 15 do { 16 date.show(); 17 cout << "\tTotal:" << Account::getTotal() << "\tcommand>"; 18 int index, day; 19 double amount; 20 string desc; 21 cin >> cmd; 22 switch (cmd) { 23 case 'd': 24 cin >> index >> amount; 25 getline(cin, desc); 26 accounts[index]->deposit(date, amount, desc); 27 break; 28 case 'w': 29 cin >> index >> amount; 30 getline(cin, desc); 31 accounts[index]->withdraw(date, amount, desc); 32 break; 33 case 's': 34 for (int i = 0; i < n; i++) { 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 } 45 else if (day > date.getMaxDay()) 46 cout << "Invalid day"; 47 else 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 date = Date(date.getYear(), date.getMonth() + 1, 1); 53 for (int i = 0; i < n; i++) { 54 accounts[i]->settle(date); 55 } 56 break; 57 } 58 } while (cmd != 'e'); 59 return 0; 60 }
在基类Account中将账户的公共操作皆声明为虚函数,可以通过基类的指针来进行各种操作,各种类型的账户对象都可以通过一个基类指针的数组来访问,提供了极大的便利,可以通过统一的方式来操作各个账户。