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

问题一:(1):含有纯虚函数的类是抽象类,代码中Publisher类声明了virtual void publish() const = 0;和virtual void use() const = 0;两个纯虚函数,因此是抽象类。
(2):不能编译通过。Publisher是抽象类,抽象类不能实例化对象,编译器会报错
问题二:(1):void publish() const override;
void use() const override;
(2):

问题三:(1):Publisher*
(2):Book、Film、Music
(3):为了实现 “多态析构”,确保删除基类指针指向的派生类对象时,能先调用派生类析构函数,再调用基类析构函数,避免内存泄漏;若删除virtual,则析构函数不具备多态性,删除基类指针时仅调用基类析构函数,派生类的成员变量无法被正确释放,导致内存泄漏
实验二:
1 #pragma once 2 #include <string> 3 #include <iostream> 4 5 // 图书描述信息类Book: 声明 6 class Book { 7 public: 8 Book(const std::string &name_, 9 const std::string &author_, 10 const std::string &translator_, 11 const std::string &isbn_, 12 double price_); 13 friend std::ostream& operator<<(std::ostream &out, const Book &book); 14 15 private: 16 std::string name; // 书名 17 std::string author; // 作者 18 std::string translator; // 译者 19 std::string isbn; // isbn号 20 double price; // 定价 21 };
1 #include <<iomanip> 2 #include <iostream> 3 #include <string> 4 #include "book.hpp" 5 6 // 图书描述信息类Book: 实现 7 Book::Book(const std::string &name_, 8 const std::string &author_, 9 const std::string &translator_, 10 const std::string &isbn_, 11 double price_) : name{name_}, author{author_}, translator{translator_}, 12 isbn{isbn_}, price{price_} {} 13 14 // 运算符<<重载实现 15 std::ostream& operator<<(std::ostream &out, const Book &book) { 16 using std::left; 17 using std::setw; 18 out << left; 19 out << setw(15) << "书名:" << book.name << '\n' 20 << setw(15) << "作者:" << book.author << '\n' 21 << setw(15) << "译者:" << book.translator << '\n' 22 << setw(15) << "ISBN:" << book.isbn << '\n' 23 << setw(15) << "定价:" << book.price; 24 return out; 25 }
1 #pragma once 2 #include <string> 3 #include "book.hpp" 4 5 // 图书销售记录类BookSale:声明 6 class BookSale { 7 public: 8 BookSale(const Book &rb_, double sales_price_, int sales_amount_); 9 int get_amount() const; // 返回销售数量 10 double get_revenue() const; // 返回营收 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 };
1 #include <<iomanip> 2 #include <iostream> 3 #include <string> 4 #include "booksale.hpp" 5 6 // 图书销售记录类BookSale:实现 7 BookSale::BookSale(const Book &rb_, 8 double sales_price_, 9 int sales_amount_) : rb{rb_}, sales_price{sales_price_}, 10 sales_amount{sales_amount_} {} 11 12 int BookSale::get_amount() const { 13 return sales_amount; 14 } 15 16 double BookSale::get_revenue() const { 17 return sales_amount * sales_price; 18 } 19 20 // 运算符<<重载实现 21 std::ostream& operator<<(std::ostream &out, const BookSale &item) { 22 using std::left; 23 using std::setw; 24 out << left; 25 out << item.rb << '\n' 26 << setw(15) << "售价:" << item.sales_price << '\n' 27 << setw(15) << "销售数量:" << item.sales_amount << '\n' 28 << setw(15) << "营收:" << item.get_revenue(); 29 return out; 30 }
1 #include "booksale.hpp" 2 #include <iostream> 3 #include <string> 4 #include <vector> 5 #include <algorithm> 6 7 // 按图书销售数额比较(降序) 8 bool compare_by_amount(const BookSale &x1, const BookSale &x2) { 9 return x1.get_amount() > x2.get_amount(); 10 } 11 12 void test() { 13 using namespace std; 14 vector<BookSale> sales_lst; // 存放图书销售记录 15 int books_number; 16 cout << "录入图书数量: "; 17 cin >> books_number; 18 cout << "录入图书销售记录" << endl; 19 for (int i = 0; i < books_number; ++i) { 20 string name, author, translator, isbn; 21 float price; 22 cout << string(20, '-') << "第" << i + 1 << "本图书信息录入" << string(20, '-') << endl; 23 cout << "录入书名: "; 24 cin >> name; 25 cout << "录入作者: "; 26 cin >> author; 27 cout << "录入译者: "; 28 cin >> translator; 29 cout << "录入isbn: "; 30 cin >> isbn; 31 cout << "录入定价: "; 32 cin >> price; 33 Book book(name, author, translator, isbn, price); 34 float sales_price; 35 int sales_amount; 36 cout << "录入售价: "; 37 cin >> sales_price; 38 cout << "录入销售数量: "; 39 cin >> sales_amount; 40 BookSale record(book, sales_price, sales_amount); 41 sales_lst.push_back(record); 42 } 43 // 按销售册数排序 44 sort(sales_lst.begin(), sales_lst.end(), compare_by_amount); 45 // 按销售册数降序输出图书销售信息 46 cout << string(20, '=') << "图书销售统计" << string(20, '=') << endl; 47 for (auto &t : sales_lst) { 48 cout << t << endl; 49 cout << string(40, '-') << endl; 50 } 51 } 52 53 int main() { 54 test(); 55 }
运行截图:

问题一:(1):重载了 2 处,分别用于Book类型和BookSale类型
(2):out << item.rb << '\n';
cout << t << endl;
out << setw(15) << "书名:" << book.name << '\n'
问题二:(1):首先定义比较函数compare_by_amount,该函数接收两个 对象,返回 “第一个对象的销售数量大于第二个对象” 的布尔值;然后调用标准库sort函数,传入销售记录向量的起始、结束和比较函数,sort函数会对元素进行降序排序。
(2):sort(sales_lst.begin(), sales_lst.end(), [](const BookSale &x1, const BookSale &x2){
return x1.get_amount() > x2.get_amount();
});
实验三:
1 #include <iostream> 2 3 // 类A的定义(数据成员为int类型) 4 class A { 5 public: 6 A(int x0, int y0); 7 void display() const; 8 private: 9 int x, y; 10 }; 11 12 // 类A构造函数实现 13 A::A(int x0, int y0) : x{x0}, y{y0} { 14 } 15 16 // 类A成员函数display实现 17 void A::display() const { 18 std::cout << x << ", " << y << '\n'; 19 } 20 21 // 类B的定义(数据成员为double类型) 22 class B { 23 public: 24 B(double x0, double y0); 25 void display() const; 26 private: 27 double x, y; 28 }; 29 30 // 类B构造函数实现 31 B::B(double x0, double y0) : x{x0}, y{y0} { 32 } 33 34 // 类B成员函数display实现 35 void B::display() const { 36 std::cout << x << ", " << y << '\n'; 37 } 38 39 // 测试函数 40 void test() { 41 std::cout << "测试类A: " << '\n'; 42 A a(3, 4); 43 a.display(); 44 45 std::cout << "\n测试类B: " << '\n'; 46 B b(3.2, 5.6); 47 b.display(); 48 } 49 50 // 主函数 51 int main() { 52 test(); 53 }
1 #include <iostream> 2 #include <string> 3 4 // 定义类模板X(类型参数T) 5 template<typename T> 6 class X { 7 public: 8 X(T x0, T y0); 9 void display(); 10 private: 11 T x, y; // 数据成员类型由模板参数T指定 12 }; 13 14 // 类模板X的构造函数实现(类外实现需加模板头) 15 template<typename T> 16 X<T>::X(T x0, T y0) : x{x0}, y{y0} { 17 } 18 19 // 类模板X的成员函数display实现(类外实现需加模板头) 20 template<typename T> 21 void X<T>::display() { 22 std::cout << x << ", " << y << '\n'; 23 } 24 25 // 测试函数(实例化不同类型的类模板X) 26 void test() { 27 std::cout << "测试1: 用int实例化类模板X" << '\n'; 28 X<int> x1(3, 4); 29 x1.display(); 30 31 std::cout << "\n测试2: 用double实例化类模板X" << '\n'; 32 X<double> x2(3.2, 5.6); 33 x2.display(); 34 35 std::cout << "\n测试3: 用string实例化类模板X" << '\n'; 36 X<std::string> x3("hello", "oop"); 37 x3.display(); 38 } 39 40 // 主函数 41 int main() { 42 test(); 43 }
运行截图:


实验四:
1 #pragma once 2 #include <string> 3 4 class MachinePet { 5 public: 6 7 MachinePet(const std::string& nickname_) : nickname(nickname_) {} 8 virtual ~MachinePet() = default; 9 std::string get_nickname() const { return nickname; } 10 virtual std::string talk() const = 0; 11 12 protected: 13 std::string nickname; 14 }; 15 16 class PetCat : public MachinePet { 17 public: 18 PetCat(const std::string& nickname_) : MachinePet(nickname_) {} 19 std::string talk() const override { return "miao wu~"; } 20 }; 21 22 class PetDog : public MachinePet { 23 public: 24 PetDog(const std::string& nickname_) : MachinePet(nickname_) {} 25 std::string talk() const override { return "wang wang~"; } 26 };
1 #include <iostream> 2 #include <memory> 3 #include <vector> 4 #include "pet.hpp" 5 void test1() { 6 std::vector<MachinePet*> pets; 7 pets.push_back(new PetCat("miku")); 8 pets.push_back(new PetDog("da huang")); 9 for (MachinePet* ptr : pets) { 10 std::cout << ptr->get_nickname() << " says " << ptr->talk() << '\n'; 11 delete ptr; 12 } 13 } 14 void test2() { 15 std::vector<std::unique_ptr<MachinePet>> pets; 16 pets.push_back(std::make_unique<PetCat>("miku")); 17 pets.push_back(std::make_unique<PetDog>("da huang")); 18 for (auto const& ptr : pets) 19 std::cout << ptr->get_nickname() << " says " << ptr->talk() << '\n'; 20 } 21 void test3() { 22 // MachinePet pet("little cutie"); // 编译报错:无法定义抽象类对象 23 const PetCat cat("miku"); 24 std::cout << cat.get_nickname() << " says " << cat.talk() << '\n'; 25 const PetDog dog("da huang"); 26 std::cout << dog.get_nickname() << " says " << dog.talk() << '\n'; 27 } 28 int main() { 29 std::cout << "测试1: 使用原始指针\n"; 30 test1(); 31 std::cout << "\n测试2: 使用智能指针\n"; 32 test2(); 33 std::cout << "\n测试3: 直接使用类\n"; 34 test3(); 35 }
运行截图:

实验五:
1 #pragma once 2 #include <iostream> 3 4 template<typename T> 5 class Complex { 6 public: 7 Complex() : real(0), imag(0) {} 8 Complex(T real_, T imag_) : real(real_), imag(imag_) {} 9 Complex(const Complex& other) : real(other.real), imag(other.imag) {} 10 11 T get_real() const { return real; } 12 T get_imag() const { return imag; } 13 14 Complex& operator+=(const Complex& other) { 15 real += other.real; 16 imag += other.imag; 17 return *this; 18 } 19 20 friend Complex operator+(const Complex& c1, const Complex& c2) { 21 return Complex(c1.real + c2.real, c1.imag + c2.imag); 22 } 23 24 bool operator==(const Complex& other) const { 25 return (real == other.real) && (imag == other.imag); 26 } 27 28 friend std::ostream& operator<<(std::ostream& out, const Complex& c) { 29 out << c.real; 30 if (c.imag >= 0) { 31 out << "+" << c.imag << "i"; 32 } 33 else { 34 out << c.imag << "i"; 35 } 36 return out; 37 } 38 39 friend std::istream& operator>>(std::istream& in, Complex& c) { 40 in >> c.real >> c.imag; 41 return in; 42 } 43 44 private: 45 T real; 46 T imag; 47 };
1 #include <iostream> 2 #include "Complex.hpp" 3 void test1() { 4 using std::cout; 5 using std::boolalpha; 6 7 Complex<int> c1(2, -5), c2(c1); 8 cout << "c1 = " << c1 << '\n'; 9 cout << "c2 = " << c2 << '\n'; 10 cout << "c1 + c2 = " << c1 + c2 << '\n'; 11 12 c1 += c2; 13 cout << "c1 = " << c1 << '\n'; 14 cout << boolalpha << (c1 == c2) << '\n'; 15 } 16 void test2() { 17 using std::cin; 18 using std::cout; 19 Complex<double> c1, c2; 20 cout << "Enter c1 and c2: "; 21 cin >> c1 >> c2; 22 cout << "c1 = " << c1 << '\n'; 23 cout << "c2 = " << c2 << '\n'; 24 const Complex<double> c3(c1); 25 cout << "c3.real = " << c3.get_real() << '\n'; 26 cout << "c3.imag = " << c3.get_imag() << '\n'; 27 } 28 int main() { 29 std::cout << "自定义类模板Complex测试1: \n"; 30 test1(); 31 std::cout << "\n自定义类模板Complex测试2: \n"; 32 test2(); 33 }
运行截图:

浙公网安备 33010602011771号