实验5

实验任务1:

publisher.hpp:

 1 #pragma once
 2 
 3 #include <string>
 4 
 5 // 发行/出版物类:Publisher (抽象类)
 6 class Publisher
 7 {
 8 public:
 9     Publisher(const std::string &name_ = ""); // 构造函数
10     virtual ~Publisher() = default;
11 
12 public:
13     virtual void publish() const = 0; // 纯虚函数,作为接口继承
14     virtual void use() const = 0;     // 纯虚函数,作为接口继承
15 
16 protected:
17     std::string name; // 发行/出版物名称
18 };
19 
20 // 图书类: Book
21 class Book : public Publisher
22 {
23 public:
24     Book(const std::string &name_ = "", const std::string &author_ = ""); // 构造函数
25 
26 public:
27     void publish() const override; // 接口
28     void use() const override;     // 接口
29 
30 private:
31     std::string author; // 作者
32 };
33 
34 // 电影类: Film
35 class Film : public Publisher
36 {
37 public:
38     Film(const std::string &name_ = "", const std::string &director_ = ""); // 构造函数
39 
40 public:
41     void publish() const override; // 接口
42     void use() const override;     // 接口
43 
44 private:
45     std::string director; // 导演
46 };
47 
48 // 音乐类:Music
49 class Music : public Publisher
50 {
51 public:
52     Music(const std::string &name_ = "", const std::string &artist_ = "");
53 
54 public:
55     void publish() const override; // 接口
56     void use() const override;     // 接口
57 
58 private:
59     std::string artist; // 音乐艺术家名称
60 };
publisher.cpp:
 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 
15 void Book::publish() const
16 {
17     std::cout << "Publishing book《" << name << "》 by " << author << '\n';
18 }
19 
20 void Book::use() const
21 {
22     std::cout << "Reading book 《" << name << "》 by " << author << '\n';
23 }
24 
25 // Film类:实现
26 Film::Film(const std::string &name_, const std::string &director_) : Publisher{name_}, director{director_}
27 {
28 }
29 
30 void Film::publish() const
31 {
32     std::cout << "Publishing film <" << name << "> directed by " << director << '\n';
33 }
34 
35 void Film::use() const
36 {
37     std::cout << "Watching film <" << name << "> directed by " << director << '\n';
38 }
39 
40 // Music类:实现
41 Music::Music(const std::string &name_, const std::string &artist_) : Publisher{name_}, artist{artist_}
42 {
43 }
44 
45 void Music::publish() const
46 {
47     std::cout << "Publishing music <" << name << "> by " << artist << '\n';
48 }
49 
50 void Music::use() const
51 {
52     std::cout << "Listening to music <" << name << "> by " << artist << '\n';
53 }
task1.cpp:
 1 #include <memory>
 2 #include <iostream>
 3 #include <vector>
 4 #include "publisher.hpp"
 5 #include "windows.h"
 6 
 7 void test1()
 8 {
 9     std::vector<Publisher *> v;
10 
11     v.push_back(new Book("Harry Potter", "J.K. Rowling"));
12     v.push_back(new Film("The Godfather", "Francis Ford Coppola"));
13     v.push_back(new Music("Blowing in the wind", "Bob Dylan"));
14 
15     for (Publisher *ptr : v)
16     {
17         ptr->publish();
18         ptr->use();
19         std::cout << '\n';
20         delete ptr;
21     }
22 }
23 
24 void test2()
25 {
26     std::vector<std::unique_ptr<Publisher>> v;
27 
28     v.push_back(std::make_unique<Book>("Harry Potter", "J.K. Rowling"));
29     v.push_back(std::make_unique<Film>("The Godfather", "Francis Ford Coppola"));
30     v.push_back(std::make_unique<Music>("Blowing in the wind", "Bob Dylan"));
31 
32     for (const auto &ptr : v)
33     {
34         ptr->publish();
35         ptr->use();
36         std::cout << '\n';
37     }
38 }
39 
40 void test3()
41 {
42     Book book("A Philosophy of Software Design", "John Ousterhout");
43     book.publish();
44     book.use();
45 }
46 
47 int main()
48 {
49     SetConsoleOutputCP(CP_UTF8);
50     std::cout << "运行时多态:纯虚函数、抽象类\n";
51 
52     std::cout << "\n测试1: 使用原始指针\n";
53     test1();
54 
55     std::cout << "\n测试2: 使用智能指针\n";
56     test2();
57 
58     std::cout << "\n测试3: 直接使用类\n";
59     test3();
60 }

运行结果:

屏幕截图 2025-12-16 000428

问题回答:

1.(1)纯虚函数决定了 Publisher 是抽象类(即包含纯虚函数的类会被编译器判定为抽象类);

            依据:virtual void publish() const = 0和virtual void use() const = 0。

   (2)不能;抽象类含纯虚函数,无法实例化。

2.(1)Book、Film、Music 必须实现:void publish() const override和void use() const override。

   (2)报错信息:声明与 "void Film::publish() const" (已声明 所在行数:41,所属文件:"C:\Users\37470\Desktop\程序\c++\大二上面向对象\实验5\code5.1\publisher.hpp") 不兼容。

            是由于函数签名不匹配导致的。

3.(1)声明类型是Publisher *,即Publisher类的指针。

   (2)实际指向的对象类型分别有Book、Film、Music(循环顺序)。

   (3)为了实现析构函数的多态调用, 保证 delete 基类指针时调用派生类析构,从而正确释放资源;

            会产生内存泄漏,导致派生类部分资源泄漏。

实验任务2:

book.hpp:
 1 #pragma once
 2 #include <string>
 3 
 4 // 图书描述信息类Book: 声明
 5 class Book
 6 {
 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 
14     friend std::ostream &operator<<(std::ostream &out, const Book &book);
15 
16 private:
17     std::string name;       // 书名
18     std::string author;     // 作者
19     std::string translator; // 译者
20     std::string isbn;       // isbn号
21     double price;           // 定价
22 };
book.cpp:
 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_}, isbn{isbn_}, price{price_}
12 {
13 }
14 
15 // 运算符<<重载实现
16 std::ostream &operator<<(std::ostream &out, const Book &book)
17 {
18     using std::left;
19     using std::setw;
20 
21     out << left;
22     out << setw(15) << "书名:" << book.name << '\n'
23         << setw(15) << "作者:" << book.author << '\n'
24         << setw(15) << "译者:" << book.translator << '\n'
25         << setw(15) << "ISBN:" << book.isbn << '\n'
26         << setw(15) << "定价:" << book.price;
27 
28     return out;
29 }
booksale.hpp:
 1 #pragma once
 2 
 3 #include <string>
 4 #include "book.hpp"
 5 
 6 // 图书销售记录类BookSales:声明
 7 class BookSale
 8 {
 9 public:
10     BookSale(const Book &rb_, double sales_price_, int sales_amount_);
11     int get_amount() const;     // 返回销售数量
12     double get_revenue() const; // 返回营收
13 
14     friend std::ostream &operator<<(std::ostream &out, const BookSale &item);
15 
16 private:
17     Book rb;
18     double sales_price; // 售价
19     int sales_amount;   // 销售数量
20 };
booksale.cpp:
 1 #include <iomanip>
 2 #include <iostream>
 3 #include <string>
 4 #include "booksale.hpp"
 5 
 6 // 图书销售记录类BookSales:实现
 7 BookSale::BookSale(const Book &rb_,
 8                    double sales_price_,
 9                    int sales_amount_) : rb{rb_}, sales_price{sales_price_}, sales_amount{sales_amount_}
10 {
11 }
12 
13 int BookSale::get_amount() const
14 {
15     return sales_amount;
16 }
17 
18 double BookSale::get_revenue() const
19 {
20     return sales_amount * sales_price;
21 }
22 
23 // 运算符<<重载实现
24 std::ostream &operator<<(std::ostream &out, const BookSale &item)
25 {
26     using std::left;
27     using std::setw;
28 
29     out << left;
30     out << item.rb << '\n'
31         << setw(15) << "售价:" << item.sales_price << '\n'
32         << setw(15) << "销售数量:" << item.sales_amount << '\n'
33         << setw(15) << "营收:" << item.get_revenue();
34 
35     return out;
36 }
task2.cpp:
 1 #include <algorithm>
 2 #include <iomanip>
 3 #include <iostream>
 4 #include <string>
 5 #include <vector>
 6 #include "booksale.hpp"
 7 
 8 // 按图书销售数量比较
 9 bool compare_by_amount(const BookSale &x1, const BookSale &x2) {
10     return x1.get_amount() > x2.get_amount();
11 }
12 
13 void test() {
14     using std::cin;
15     using std::cout;
16     using std::getline;
17     using std::sort;
18     using std::string;
19     using std::vector;
20     using std::ws;
21 
22     vector<BookSale> sales_records;         // 图书销售记录表
23 
24     int books_number;
25     cout << "录入图书数量: ";
26     cin >> books_number;
27 
28     cout << "录入图书销售记录\n";
29     for(int i = 0; i < books_number; ++i) {
30         string name, author, translator, isbn;
31         double price;
32         cout << string(20, '-') << "" << i+1 << "本图书信息录入" << string(20, '-') << '\n';
33         cout << "录入书名: "; getline(cin>>ws, name);
34         cout << "录入作者: "; getline(cin>>ws, author);
35         cout << "录入译者: "; getline(cin>>ws, translator);
36         cout << "录入isbn: "; getline(cin>>ws, isbn);
37         cout << "录入定价: "; cin >> price;
38 
39         Book book(name, author, translator, isbn, price);
40 
41         double sales_price;
42         int sales_amount;
43 
44         cout << "录入售价: "; cin >> sales_price;
45         cout << "录入销售数量: "; cin >> sales_amount;
46 
47         BookSale record(book, sales_price, sales_amount);
48         sales_records.push_back(record);
49     }
50 
51     // 按销售册数排序
52     sort(sales_records.begin(), sales_records.end(), compare_by_amount);
53 
54     // 按销售册数降序输出图书销售信息
55     cout << string(20, '=') <<  "图书销售统计" << string(20, '=') << '\n';
56     for(auto &record: sales_records) {
57         cout << record << '\n';
58         cout << string(40, '-') << '\n';
59     }
60 }
61 
62 int main() {
63     test();
64 }

运行结果:

屏幕截图 2025-12-16 095201

问题回答:

1.(1)运算符 << 被重载了2次;分别用于输出Book类型的对象和输出BookSale类型的对象。

   (2)

1 for (auto &record : sales_records)
2     {
3         cout << record << '\n';
4         cout << string(40, '-') << '\n';
5     }

 1 std::ostream &operator<<(std::ostream &out, const BookSale &item)
 2 {
 3     using std::left;
 4     using std::setw;
 5 
 6     out << left;
 7     out << item.rb << '\n'
 8         << setw(15) << "售价:" << item.sales_price << '\n'
 9         << setw(15) << "销售数量:" << setw(15) <<item.sales_amount << '\n'
10         << setw(15) << "营收:" << item.get_revenue();
11 
12     return out;
13 }

中的

1 out << item.rb << '\n'

2.(1)

1 sort(sales_records.begin(), sales_records.end(), compare_by_amount);

     和

1 bool compare_by_amount(const BookSale &x1, const BookSale &x2)
2 {
3     return x1.get_amount() > x2.get_amount();
4 }

共同作用,通过自定义比较函数,传入容器中,用sort算法排序。

    (2)

1 sort(sales_records.begin(), sales_records.end(),
2      [](const BookSale &x1, const BookSale &x2) { 
3          return x1.get_amount() > x2.get_amount(); 
4      });

 

实验任务3:

task3_1.cpp:
 1 #include <iostream>
 2 #include "windows.h"
 3 
 4 // 类A的定义
 5 class A
 6 {
 7 public:
 8     A(int x0, int y0);
 9     void display() const;
10 
11 private:
12     int x, y;
13 };
14 
15 A::A(int x0, int y0) : x{x0}, y{y0}
16 {
17 }
18 
19 void A::display() const
20 {
21     std::cout << x << ", " << y << '\n';
22 }
23 
24 // 类B的定义
25 class B
26 {
27 public:
28     B(double x0, double y0);
29     void display() const;
30 
31 private:
32     double x, y;
33 };
34 
35 B::B(double x0, double y0) : x{x0}, y{y0}
36 {
37 }
38 
39 void B::display() const
40 {
41     std::cout << x << ", " << y << '\n';
42 }
43 
44 void test()
45 {
46     std::cout << "测试类A: " << '\n';
47     A a(3, 4);
48     a.display();
49 
50     std::cout << "\n测试类B: " << '\n';
51     B b(3.2, 5.6);
52     b.display();
53 }
54 
55 int main()
56 {
57     SetConsoleOutputCP(CP_UTF8);
58     test();
59 }
运行结果:
屏幕截图 2025-12-16 003818

 

task3_2.cpp:
 1 #include <iostream>
 2 #include <string>
 3 #include "windows.h"
 4 
 5 // 定义类模板
 6 template <typename T>
 7 class X
 8 {
 9 public:
10     X(T x0, T y0);
11     void display();
12 
13 private:
14     T x, y;
15 };
16 
17 template <typename T>
18 X<T>::X(T x0, T y0) : x{x0}, y{y0}
19 {
20 }
21 
22 template <typename T>
23 void X<T>::display()
24 {
25     std::cout << x << ", " << y << '\n';
26 }
27 
28 void test()
29 {
30     std::cout << "测试1: 用int实例化类模板X" << '\n';
31     X<int> x1(3, 4);
32     x1.display();
33 
34     std::cout << "\n测试2:用double实例化类模板X" << '\n';
35     X<double> x2(3.2, 5.6);
36     x2.display();
37 
38     std::cout << "\n测试3: 用string实例化类模板X" << '\n';
39     X<std::string> x3("hello", "oop");
40     x3.display();
41 }
42 
43 int main()
44 {
45     SetConsoleOutputCP(CP_UTF8);
46     test();
47 }

运行结果:

屏幕截图 2025-12-16 003833

 

实验任务4:

pet.hpp:

 1 #pragma once
 2 #include <string>
 3 
 4 class MachinePet
 5 {
 6     private :
 7         std::string nickname;
 8     public :
 9         MachinePet(const std::string &nickname_): nickname{nickname_} {}
10         virtual ~MachinePet() = default;
11         virtual std::string talk() const = 0; 
12         std::string get_nickname() const { return nickname; }
13 
14 };
15 
16 class PetCat : public MachinePet
17 {
18     public :
19         PetCat(const std::string &nickname_): MachinePet{nickname_} {}
20         std::string talk() const override { return "miao wu~"; }
21 };
22 
23 class PetDog : public MachinePet
24 {
25     public :
26         PetDog(const std::string &nickname_): MachinePet{nickname_} {}
27         std::string talk() const override { return "wang wang~"; }
28 };
task4.cpp:
 1 #include <iostream>
 2 #include <memory>
 3 #include <vector>
 4 #include "pet.hpp"
 5 #include "windows.h"
 6 
 7 void test1()
 8 {
 9     std::vector<MachinePet *> pets;
10 
11     pets.push_back(new PetCat("miku"));
12     pets.push_back(new PetDog("da huang"));
13 
14     for (MachinePet *ptr : pets)
15     {
16         std::cout << ptr->get_nickname() << " says " << ptr->talk() << '\n';
17         delete ptr; // 须手动释放资源
18     }
19 }
20 
21 void test2()
22 {
23     std::vector<std::unique_ptr<MachinePet>> pets;
24 
25     pets.push_back(std::make_unique<PetCat>("miku"));
26     pets.push_back(std::make_unique<PetDog>("da huang"));
27 
28     for (auto const &ptr : pets)
29         std::cout << ptr->get_nickname() << " says " << ptr->talk() << '\n';
30 }
31 
32 void test3()
33 {
34     // MachinePet pet("little cutie");   // 编译报错:无法定义抽象类对象
35 
36     const PetCat cat("miku");
37     std::cout << cat.get_nickname() << " says " << cat.talk() << '\n';
38 
39     const PetDog dog("da huang");
40     std::cout << dog.get_nickname() << " says " << dog.talk() << '\n';
41 }
42 
43 int main()
44 {
45     SetConsoleOutputCP(CP_UTF8);
46     std::cout << "测试1: 使用原始指针\n";
47     test1();
48 
49     std::cout << "\n测试2: 使用智能指针\n";
50     test2();
51 
52     std::cout << "\n测试3: 直接使用类\n";
53     test3();
54 }

运行结果:

屏幕截图 2025-12-16 010020

 

试验任务5:

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

 运行结果:

屏幕截图 2025-12-16 104518

 

posted @ 2025-12-16 10:48  noeleven  阅读(3)  评论(0)    收藏  举报