实验 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.hpp

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 }
Publisher.cpp

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 }
task 1.cpp

image

 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.hpp

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 }
Book.cpp

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.hpp

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 }
BookSale.cpp

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 }
task2.cpp

image

 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 4.cpp

image

 

 

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 }
task 5.cpp

image

 

posted @ 2025-12-17 00:28  璐Luzi  阅读(3)  评论(0)    收藏  举报