实验 5
task 1
Publisher.hpp
1 #pragma once 2 #include<string> 3 4 class Publisher { 5 public: 6 Publisher(const std::string& name_ = " "); 7 virtual ~Publisher() = default; 8 9 public: 10 virtual void publish() const = 0; 11 virtual void use() const = 0; 12 13 protected: 14 std::string name; 15 }; 16 17 class Book :public Publisher { 18 public: 19 Book(const std::string& name_ = " ", const std::string& author_ = " "); 20 21 public: 22 void publish() const override; 23 void use() const override; 24 25 private: 26 std::string author; 27 }; 28 29 class Film :public Publisher { 30 public: 31 Film(const std::string &name_ = " ", const std::string &director_ = " "); 32 33 public: 34 void publish() const override; 35 void use() const override; 36 37 private: 38 std::string director; 39 }; 40 41 class Music :public Publisher { 42 public: 43 Music(const std::string& name_ = " ", const std::string& artist_ = " "); 44 45 public: 46 void publish() const override; 47 void use() const override; 48 49 private: 50 std::string artist; 51 };
Publisher.cpp
1 #include<iostream> 2 #include<string> 3 #include"Publisher.hpp" 4 5 Publisher::Publisher(const std::string& name_):name{name_}{} 6 7 Book::Book(const std::string& name_ , const std::string& author_ ):Publisher{name_},author{author_}{} 8 9 void Book::publish() const { 10 std::cout << "Publishing book 《" << name << "》 by" << author << '\n'; 11 } 12 13 void Book::use() const { 14 std::cout << "Reading book 《" << name << "》 by" << author << '\n'; 15 } 16 17 Film::Film(const std::string& name_ , const std::string& director_ ):Publisher{name_},director{director_}{} 18 19 void Film::publish() const { 20 std::cout << "Publishing film <" << name << "> by" << director << '\n'; 21 } 22 23 void Film::use() const { 24 std::cout << "Watching film <" << name << "> by" << director << '\n'; 25 } 26 27 Music::Music(const std::string& name_ , const std::string& artist_ ):Publisher{name_},artist{artist_}{} 28 29 void Music::publish() const { 30 std::cout << "Publishing music <" << name << "> by" << artist << '\n'; 31 } 32 33 void Music::use() const { 34 std::cout << "Listening to music <" << name << "> by" << artist << '\n'; 35 }
task1.cpp
1 #include<memory> 2 #include<iostream> 3 #include<vector> 4 #include"Publisher.hpp" 5 6 void test1() { 7 std::vector<Publisher*> v; 8 9 v.push_back(new Book("Harry Potter", "J.K. Rowling")); 10 v.push_back(new Film("The Godfather", "Francis Ford Coppola")); 11 v.push_back(new Music("Blowing in the wind", "Bob Dylan")); 12 13 for (Publisher* ptr : v) { 14 ptr->publish(); 15 ptr->use(); 16 std::cout << '\n'; 17 delete ptr; 18 } 19 } 20 21 void test2() { 22 std::vector<std::unique_ptr<Publisher>> v; 23 v.push_back(std::make_unique<Book>("Harry Potter", "J.K. Rowling")); 24 v.push_back(std::make_unique<Film>("The Godfather", "Francis Ford Coppola")); 25 v.push_back(std::make_unique<Music>("Blowing in the wind", "Bob Dylan")); 26 27 for (const auto& ptr : v) { 28 ptr->publish(); 29 ptr->use(); 30 std::cout << '\n'; 31 } 32 } 33 34 void test3() { 35 Book book("A Philosophy of Software Design", "John Ousterhout"); 36 book.publish(); 37 book.use(); 38 } 39 40 int main() { 41 std::cout << "运行时多态:纯虚函数、抽象类\n"; 42 43 std::cout << "\n测试1: 使用原始指针\n"; 44 test1(); 45 46 std::cout << "\n测试2: 使用智能指针\n"; 47 test2(); 48 49 std::cout << "\n测试3: 直接使用类\n"; 50 test3(); 51 }

Q1:
(1)Publisher类中的虚函数决定了其是抽象类,具体依据为:virtual ~Publisher() = default; virtual void publish() const = 0; virtual void use() const = 0
(2)不能通过编译,Publisher类是抽象类,抽象不能创建具体对象。
Q2:
(1)必须实现publish和use
Book:
void publish() const override;
void use() const override;
Film:
void publish() const override;
void use() const override;
Music:
void publish() const override;
void use() const override;
(2)报错信息为:使用"override"声明的成员函数不能重写基类成员
Q3:
(1)声明类型为:Publisher *,指向Publisher类的裸指针
(2)1.Book类 2.Film类 3.Music类
(3)virtual可以让编译器先执行派生类析构,再执行基类析构,避免内存泄漏;若删除virtual,执行delete ptr,仅有基类的析构函数会被执行,派生类的析构函数不会被执行,导致内存泄漏。
task 2
Book.hpp
1 #pragma once 2 #include<string> 3 4 class Book { 5 public: 6 Book(const std::string& name_, const std::string& author_, const std::string& translator_, const std::string& isbn_, double price_); 7 8 friend std::ostream& operator<<(std::ostream& out, const Book& book); 9 10 private: 11 std::string name; 12 std::string author; 13 std::string translator; 14 std::string isbn; 15 double price; 16 };
Book.cpp
1 #include "Book.hpp" 2 #include<iomanip> 3 #include<iostream> 4 #include<string> 5 6 Book::Book(const std::string& name_, const std::string& author_, const std::string& translator_, const std::string& isbn_, double price_) :name{ name_ }, author{ author_ }, translator{ translator_ }, isbn{ isbn_ }, price { price_ } {} 7 8 std::ostream& operator<<(std::ostream& out, const Book& book) { 9 using std::left; 10 using std::setw; 11 12 out << left; 13 out << setw(15) << "书名:" << book.name << '\n' 14 << setw(15) << "作者:" << book.author << '\n' 15 << setw(15) << "译者:" << book.translator << '\n' 16 << setw(15) << "ISBN:" << book.isbn << '\n' 17 << setw(15) << "定价:" << book.price; 18 19 return out; 20 }
BookSale.hpp
1 #pragma once 2 #include<string> 3 #include"Book.hpp" 4 5 class BookSale { 6 public: 7 BookSale(const Book& rb_, double sales_price_, int sales_amount_); 8 int get_amount() const; 9 double get_revenue() const; 10 11 friend std::ostream& operator<<(std::ostream& out, const BookSale& item); 12 13 private: 14 Book rb; 15 double sales_price; 16 int sales_amount; 17 };
BookSale.cpp
1 #include "BookSale.hpp" 2 #include<iomanip> 3 #include<string> 4 #include<iostream> 5 6 BookSale::BookSale(const Book& rb_, double sales_price_, int sales_amount_):rb{rb_},sales_price{sales_price_},sales_amount{sales_amount_}{} 7 8 int BookSale::get_amount() const { 9 return sales_amount; 10 } 11 12 double BookSale::get_revenue() const { 13 return sales_amount * sales_price; 14 } 15 16 std::ostream& operator<<(std::ostream& out, const BookSale& item) { 17 using std::left; 18 using std::setw; 19 20 out << left; 21 out << item.rb << '\n' 22 << setw(15) << "售价:" << item.sales_price << '\n' 23 << setw(15) << "销售数量:" << item.sales_amount << '\n' 24 << setw(15) << "营收:" << item.get_revenue(); 25 26 return out; 27 }
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 20 cout << "录入图书销售记录" << endl; 21 for (int i = 0; i < books_number;++i) { 22 string name, author, translator, isbn; 23 float price; 24 cout << string(20, '-') << "第" << i + 1 << "本图书信息录入" << string(20, '-') << endl; 25 cout << "录入书名: "; cin >> name; 26 cout << "录入作者: "; cin >> author; 27 cout << "录入译者: "; cin >> translator; 28 cout << "录入isbn: "; cin >> isbn; 29 cout << "录入定价: "; cin >> price; 30 31 Book book(name, author, translator, isbn, price); 32 33 float sales_price; 34 int sales_amount; 35 36 cout << "录入售价: "; cin >> sales_price; 37 cout << "录入销售数量: "; cin >> sales_amount; 38 39 BookSale record(book, sales_price, sales_amount); 40 sales_lst.push_back(record); 41 } 42 43 sort(sales_lst.begin(), sales_lst.end(), compare_by_amount); 44 45 cout << string(20, '=') << "图书销售统计" << string(20, '=') << endl; 46 for (auto& t : sales_lst) { 47 cout << t << endl; 48 cout << string(40, '-') << endl; 49 } 50 } 51 52 int main() { 53 test(); 54 }

Q1:
(1)两次重载。第一次:std::ostream& operator<<(std::ostream& out, const Book& book),用于输出Book类对象;第二次:std::ostream& operator<<(std::ostream& out, const BookSale& item),用于输出BookSale类对象。
(2)使用重载<<的代码
for (auto& t : sales_lst) { cout << t << endl; cout << string(40, '-') << endl; }
out << item.rb << '\n'
Q2:
bool compare_by_amount(const BookSale& x1, const BookSale& x2) { return x1.get_amount() > x2.get_amount(); }
如果x1的销售量比x2的销售量大,bool返回值为true,则x1排在前面
sort(sales_lst.begin(), sales_lst.end(), compare_by_amount);
用<algorithm>标准库中的sort函数实现排序
task3
实验文档说无需上传,故略
task4
Pet.hpp
1 #pragma once 2 #include<iostream> 3 #include<string> 4 5 class MachinePet { 6 public: 7 MachinePet(const std::string nickname_ = " "); 8 virtual ~MachinePet() = default; 9 10 virtual std::string get_nickname() const = 0; 11 virtual std::string talk() const = 0; 12 13 protected: 14 std::string nickname; 15 }; 16 17 class PetCat :public MachinePet { 18 public: 19 PetCat(const std::string nickname_ = " "); 20 21 std::string get_nickname() const override; 22 std::string talk() const override; 23 }; 24 25 class PetDog :public MachinePet { 26 public: 27 PetDog(const std::string nickname_ = " "); 28 29 std::string get_nickname() const override; 30 std::string talk() const override; 31 }; 32 33 MachinePet::MachinePet(const std::string nickname_) :nickname{ nickname_ } {} 34 35 PetCat::PetCat(const std::string nickname_) :MachinePet{ nickname_ } {} 36 37 std::string PetCat::get_nickname() const { 38 return nickname; 39 } 40 41 std::string PetCat::talk() const { 42 return "喵喵"; 43 } 44 45 PetDog::PetDog(const std::string nickname_) :MachinePet{ nickname_ } {} 46 47 std::string PetDog::get_nickname() const { 48 return nickname; 49 } 50 51 std::string PetDog::talk() const { 52 return "汪汪"; 53 }
task 4.cpp
1 #include <iostream> 2 #include <memory> 3 #include <vector> 4 #include "Pet.hpp" 5 6 void test1() { 7 std::vector<MachinePet*> pets; 8 pets.push_back(new PetCat("miku")); 9 pets.push_back(new PetDog("da huang")); 10 for (MachinePet* ptr : pets) { 11 std::cout << ptr->get_nickname() << " says " << ptr->talk() << '\n'; 12 delete ptr; 13 } 14 } 15 16 void test2() { 17 std::vector<std::unique_ptr<MachinePet>> pets; 18 pets.push_back(std::make_unique<PetCat>("miku")); 19 pets.push_back(std::make_unique<PetDog>("da huang")); 20 for (auto const& ptr : pets) 21 std::cout << ptr->get_nickname() << " says " << ptr->talk() << '\n'; 22 } 23 24 void test3() { 25 const PetCat cat("miku"); 26 std::cout << cat.get_nickname() << " says " << cat.talk() << '\n'; 27 28 const PetDog dog("da huang"); 29 std::cout << dog.get_nickname() << " says " << dog.talk() << '\n'; 30 } 31 32 int main() { 33 std::cout << "测试1: 使用原始指针\n"; 34 test1(); 35 36 std::cout << "\n测试2: 使用智能指针\n"; 37 test2(); 38 39 std::cout << "\n测试3: 直接使用类\n"; 40 test3(); 41 }

task 5
Complex.hpp
1 #pragma once 2 #include<iostream> 3 4 template<typename T> 5 class Complex { 6 public: 7 Complex(T real_ = 0, T imag_ = 0); 8 Complex(const Complex& c); 9 Complex& operator+=(const Complex& c); 10 ~Complex() = default; 11 12 T get_real() const; 13 T get_imag() const; 14 15 template<typename T> 16 friend Complex<T> operator+(const Complex<T>& c1, const Complex<T>& c2); 17 18 template<typename T> 19 friend bool operator==(const Complex<T>& c1, const Complex<T>& c2); 20 21 template<typename T> 22 friend std::istream& operator>>(std::istream& in, Complex<T>& c); 23 24 template<typename T> 25 friend std::ostream& operator<<(std::ostream& out, const Complex<T>& c); 26 27 private: 28 T real; 29 T imag; 30 }; 31 32 template<typename T> 33 Complex<T>::Complex(T real_,T imag_):real{real_},imag{imag_}{} 34 35 template<typename T> 36 Complex<T>::Complex(const Complex& c):real{c.real},imag{c.imag}{} 37 38 template<typename T> 39 Complex<T>& Complex<T>::operator+=(const Complex& c) { 40 real += c.real; 41 imag += c.imag; 42 43 return *this; 44 } 45 46 template<typename T> 47 T Complex<T>::get_real() const { 48 return real; 49 } 50 51 template<typename T> 52 T Complex<T>::get_imag() const { 53 return imag; 54 } 55 56 template<typename T> 57 Complex<T> operator+(const Complex<T>& c1, const Complex<T>& c2) { 58 return Complex<T>(c1.real + c2.real, c1.imag + c2.imag); 59 } 60 61 template<typename T> 62 bool operator==(const Complex<T>& c1, const Complex<T>& c2) { 63 return (c1.real == c2.real && c1.imag == c2.imag); 64 } 65 66 template<typename T> 67 std::istream& operator>>(std::istream& in, Complex<T>& c) { 68 in >> c.real >> c.imag; 69 return in; 70 } 71 72 template<typename T> 73 std::ostream& operator<<(std::ostream& out,const Complex<T>& c) { 74 if (c.imag >= 0) 75 out << c.real << " + " << c.imag << 'i'; 76 else 77 out << c.real << " - " << -c.imag << 'i'; 78 79 return out; 80 }
task 5.cpp
1 #include <iostream> 2 #include "Complex.hpp" 3 4 void test1() { 5 using std::cout; 6 using std::boolalpha; 7 8 Complex<int> c1(2, -5), c2(c1); 9 10 cout << "c1 = " << c1 << '\n'; 11 cout << "c2 = " << c2 << '\n'; 12 cout << "c1 + c2 = " << c1 + c2 << '\n'; 13 14 c1 += c2; 15 cout << "c1 = " << c1 << '\n'; 16 cout << boolalpha << (c1 == c2) << '\n'; 17 } 18 19 void test2() { 20 using std::cin; 21 using std::cout; 22 23 Complex<double> c1, c2; 24 cout << "Enter c1 and c2: "; 25 cin >> c1 >> c2; 26 cout << "c1 = " << c1 << '\n'; 27 cout << "c2 = " << c2 << '\n'; 28 29 const Complex<double> c3(c1); 30 cout << "c3.real = " << c3.get_real() << '\n'; 31 cout << "c3.imag = " << c3.get_imag() << '\n'; 32 } 33 34 int main() { 35 std::cout << "自定义类模板Complex测试1: \n"; 36 test1(); 37 38 std::cout << "\n自定义类模板Complex测试2: \n"; 39 test2(); 40 }

浙公网安备 33010602011771号