实验五 多态
任务1
publisher.hpp
#pragma once #include <string> class Publisher { public: Publisher(const std::string &name_ = ""); virtual ~Publisher() = default; public: virtual void publish() const = 0; virtual void use() const = 0; protected: std::string name; }; class Book: public Publisher { public: Book(const std::string &name_ = "", const std::string &author_ = ""); public: void publish() const override; void use() const override; private: std::string author; }; class Film: public Publisher { public: Film(const std::string &name_ = "", const std::string &director_ = ""); // 鏋勯€犲嚱鏁? public: void publish() const override; void use() const override; private: std::string director; }; class Music: public Publisher { public: Music(const std::string &name_ = "", const std::string &artist_ = ""); public: void publish() const override; void use() const override; private: std::string artist; };
publisher.cpp
#include <iostream> #include <string> #include "publisher.hpp" // Publisher绫伙細瀹炵幇 Publisher::Publisher(const std::string &name_): name {name_} { } // Book绫? 瀹炵幇 Book::Book(const std::string &name_ , const std::string &author_ ): Publisher{name_}, author{author_} { } void Book::publish() const { std::cout << "Publishing book銆? << name << "銆?by " << author << '\n'; } void Book::use() const { std::cout << "Reading book 銆? << name << "銆?by " << author << '\n'; } // Film绫伙細瀹炵幇 Film::Film(const std::string &name_, const std::string &director_):Publisher{name_},director{director_} { } void Film::publish() const { std::cout << "Publishing film <" << name << "> directed by " << director << '\n'; } void Film::use() const { std::cout << "Watching film <" << name << "> directed by " << director << '\n'; } // Music绫伙細瀹炵幇 Music::Music(const std::string &name_, const std::string &artist_): Publisher{name_}, artist{artist_} { } void Music::publish() const { std::cout << "Publishing music <" << name << "> by " << artist << '\n'; } void Music::use() const { std::cout << "Listening to music <" << name << "> by " << artist << '\n'; }
task1.cpp
#include <memory> #include <iostream> #include <vector> #include "publisher.hpp" void test1() { std::vector<Publisher *> v; v.push_back(new Book("Harry Potter", "J.K. Rowling")); v.push_back(new Film("The Godfather", "Francis Ford Coppola")); v.push_back(new Music("Blowing in the wind", "Bob Dylan")); for(Publisher *ptr: v) { ptr->publish(); ptr->use(); std::cout << '\n'; delete ptr; } } void test2() { std::vector<std::unique_ptr<Publisher>> v; v.push_back(std::make_unique<Book>("Harry Potter", "J.K. Rowling")); v.push_back(std::make_unique<Film>("The Godfather", "Francis Ford Coppola")); v.push_back(std::make_unique<Music>("Blowing in the wind", "Bob Dylan")); for(const auto &ptr: v) { ptr->publish(); ptr->use(); std::cout << '\n'; } } void test3() { Book book("A Philosophy of Software Design", "John Ousterhout"); book.publish(); book.use(); } int main() { std::cout << "杩愯鏃跺鎬侊細绾櫄鍑芥暟銆佹娊璞$被\n"; std::cout << "\n娴嬭瘯1: 浣跨敤鍘熷鎸囬拡\n"; test1(); std::cout << "\n娴嬭瘯2: 浣跨敤鏅鸿兘鎸囬拡\n"; test2(); std::cout << "\n娴嬭瘯3: 鐩存帴浣跨敤绫籠n"; test3(); }
运行结果如下:

问题1:
(1)含有纯虚函数:
virtual void publish() const = 0;
virtual void use() const = 0;
(2)
不能,
Publisher p是抽象类,不能直接声明
问题二:
(1):publish函数和use函数
void publish() const override;
void use() const override;
(2)“void Film::use(void)”:“Film”中没有找到重载的成员函数
对非静态成员“Publisher::name”的非法引用
问题3:
(1)Publisher *型
(2)Book->Film->Music
(3)使基类指针在删除派生类对象的时候正确调用派生类对象的析构函数
任务2
book.hpp
#pragma once #include <string> // 鍥句功鎻忚堪淇℃伅绫籅ook: 澹版槑 class Book { public: Book(const std::string &name_, const std::string &author_, const std::string &translator_, const std::string &isbn_, double price_); friend std::ostream& operator<<(std::ostream &out, const Book &book); private: std::string name; // 涔﹀悕 std::string author; // 浣滆€? std::string translator; // 璇戣€? std::string isbn; // isbn鍙? double price; // 瀹氫环 };
book.cpp
#include <iomanip> #include <iostream> #include <string> #include "book.hpp" // 鍥句功鎻忚堪淇℃伅绫籅ook: 瀹炵幇 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_} { } // 杩愮畻绗?<閲嶈浇瀹炵幇 std::ostream& operator<<(std::ostream &out, const Book &book) { using std::left; using std::setw; out << left; out << setw(15) << "涔﹀悕:" << book.name << '\n' << setw(15) << "浣滆€?" << book.author << '\n' << setw(15) << "璇戣€?" << book.translator << '\n' << setw(15) << "ISBN:" << book.isbn << '\n' << setw(15) << "瀹氫环:" << book.price; return out; }
booksale.hpp
#pragma once #include <string> #include "book.hpp" // 鍥句功閿€鍞褰曠被BookSales锛氬0鏄? class BookSale { public: BookSale(const Book &rb_, double sales_price_, int sales_amount_); int get_amount() const; // 杩斿洖閿€鍞暟閲? double get_revenue() const; // 杩斿洖钀ユ敹 friend std::ostream& operator<<(std::ostream &out, const BookSale &item); private: Book rb; double sales_price; // 鍞环 int sales_amount; // 閿€鍞暟閲? };
booksale.cpp
#include <iomanip> #include <iostream> #include <string> #include "booksale.hpp" // 鍥句功閿€鍞褰曠被BookSales锛氬疄鐜? BookSale::BookSale(const Book &rb_, double sales_price_, int sales_amount_): rb{rb_}, sales_price{sales_price_}, sales_amount{sales_amount_} { } int BookSale::get_amount() const { return sales_amount; } double BookSale::get_revenue() const { return sales_amount * sales_price; } // 杩愮畻绗?<閲嶈浇瀹炵幇 std::ostream& operator<<(std::ostream &out, const BookSale &item) { using std::left; using std::setw; out << left; out << item.rb << '\n' << setw(15) << "鍞环:" << item.sales_price << '\n' << setw(15) << "閿€鍞暟閲?" << item.sales_amount << '\n' << setw(15) << "钀ユ敹:" << item.get_revenue(); return out; }
task2.cpp
#include <algorithm> #include <iomanip> #include <iostream> #include <string> #include <vector> #include "booksale.hpp" // 鎸夊浘涔﹂攢鍞暟閲忔瘮杈? bool compare_by_amount(const BookSale &x1, const BookSale &x2) { return x1.get_amount() > x2.get_amount(); } void test() { using std::cin; using std::cout; using std::getline; using std::sort; using std::string; using std::vector; using std::ws; vector<BookSale> sales_records; // 鍥句功閿€鍞褰曡〃 int books_number; cout << "褰曞叆鍥句功鏁伴噺: "; cin >> books_number; cout << "褰曞叆鍥句功閿€鍞褰昞n"; for(int i = 0; i < books_number; ++i) { string name, author, translator, isbn; double price; cout << string(20, '-') << "绗? << i+1 << "鏈浘涔︿俊鎭綍鍏? << string(20, '-') << '\n'; cout << "褰曞叆涔﹀悕: "; getline(cin>>ws, name); cout << "褰曞叆浣滆€? "; getline(cin>>ws, author); cout << "褰曞叆璇戣€? "; getline(cin>>ws, translator); cout << "褰曞叆isbn: "; getline(cin>>ws, isbn); cout << "褰曞叆瀹氫环: "; cin >> price; Book book(name, author, translator, isbn, price); double sales_price; int sales_amount; cout << "褰曞叆鍞环: "; cin >> sales_price; cout << "褰曞叆閿€鍞暟閲? "; cin >> sales_amount; BookSale record(book, sales_price, sales_amount); sales_records.push_back(record); } // 鎸夐攢鍞唽鏁版帓搴? sort(sales_records.begin(), sales_records.end(), compare_by_amount); // 鎸夐攢鍞唽鏁伴檷搴忚緭鍑哄浘涔﹂攢鍞俊鎭? cout << string(20, '=') << "鍥句功閿€鍞粺璁? << string(20, '=') << '\n'; for(auto &record: sales_records) { cout << record << '\n'; cout << string(40, '-') << '\n'; } } int main() { test();
运行结果如下:

问题1:
(1)两处,分别用于BookSale类和Book类
(2)
std::ostream& operator<<(std::ostream &out, const BookSale &item) {
using std::left;
using std::setw;
out << left;
out << item.rb << '\n'
<< setw(15) << "售价:" << item.sales_price << '\n'
<< setw(15) << "销售数量:" << item.sales_amount << '\n'
<< setw(15) << "营收:" << item.get_revenue();
return out;
}
std::ostream& operator<<(std::ostream &out, const Book &book) {
using std::left;
using std::setw;
out << left;
out << setw(15) << "书名:" << book.name << '\n'
<< setw(15) << "作者:" << book.author << '\n'
<< setw(15) << "译者:" << book.translator << '\n'
<< setw(15) << "ISBN:" << book.isbn << '\n'
<< setw(15) << "定价:" << book.price;
return out;
}
问题2:
(1)sort函数
任务4
task4.cpp
#include <iostream> #include <memory> #include <vector> #include "pet.hpp" void test1() { std::vector<MachinePet *> pets; pets.push_back(new PetCat("miku")); pets.push_back(new PetDog("da huang")); for(MachinePet *ptr: pets) { std::cout << ptr->get_nickname() << " says " << ptr->talk() << '\n'; delete ptr; // 椤绘墜鍔ㄩ噴鏀捐祫婧? } } void test2() { std::vector<std::unique_ptr<MachinePet>> pets; pets.push_back(std::make_unique<PetCat>("miku")); pets.push_back(std::make_unique<PetDog>("da huang")); for(auto const &ptr: pets) std::cout << ptr->get_nickname() << " says " << ptr->talk() << '\n'; } void test3() { // MachinePet pet("little cutie"); // 缂栬瘧鎶ラ敊锛氭棤娉曞畾涔夋娊璞$被瀵硅薄 const PetCat cat("miku"); std::cout << cat.get_nickname() << " says " << cat.talk() << '\n'; const PetDog dog("da huang"); std::cout << dog.get_nickname() << " says " << dog.talk() << '\n'; } int main() { std::cout << "娴嬭瘯1: 浣跨敤鍘熷鎸囬拡\n"; test1(); std::cout << "\n娴嬭瘯2: 浣跨敤鏅鸿兘鎸囬拡\n"; test2(); std::cout << "\n娴嬭瘯3: 鐩存帴浣跨敤绫籠n"; test3(); }
pets.hpp
#pragma once #include <iostream> #include <string> using std::string; class MachinePet { string nickname; public: MachinePet(string name) ; string get_nickname() const; virtual string talk()const = 0; }; class PetCat :public MachinePet { public: PetCat(string name); string talk()const; }; class PetDog :public MachinePet { public: PetDog(string name); string talk()const; };
pet.cpp
#include "pet.hpp" MachinePet::MachinePet( string name):nickname(name) {} string MachinePet::get_nickname() const { return nickname; } PetCat::PetCat( string name):MachinePet(name) {} string PetCat::talk()const { return "miao wu~" ; } PetDog::PetDog( string name) :MachinePet(name) {} string PetDog::talk()const { return "wang wang~" ; }
运行结果如下:

任务5
task5.cpp
#include <iostream> #include "Complex.hpp" void test1() { using std::cout; using std::boolalpha; Complex<int> c1(2, -5), c2(c1); cout << "c1 = " << c1 << '\n'; cout << "c2 = " << c2 << '\n'; cout << "c1 + c2 = " << c1 + c2 << '\n'; c1 += c2; cout << "c1 = " << c1 << '\n'; cout << boolalpha << (c1 == c2) << '\n'; } void test2() { using std::cin; using std::cout; Complex<double> c1, c2; cout << "Enter c1 and c2: "; cin >> c1 >> c2; cout << "c1 = " << c1 << '\n'; cout << "c2 = " << c2 << '\n'; const Complex<double> c3(c1); cout << "c3.real = " << c3.get_real() << '\n'; cout << "c3.imag = " << c3.get_imag() << '\n'; } int main() { std::cout << "鑷畾涔夌被妯℃澘Complex娴嬭瘯1: \n"; test1(); std::cout << "\n鑷畾涔夌被妯℃澘Complex娴嬭瘯2: \n"; test2(); }
Complex.hpp
#pragma once #include <iostream> using std::istream; using std::ostream; template <typename T> class Complex { public : Complex(); Complex(T real_n,T image_n); Complex( const Complex& other); Complex operator+(const Complex& other); Complex & operator+=(const Complex& other); bool operator==(const Complex& other)const ; T get_real() const ; T get_imag() const ; template <typename T> friend istream & operator>>(istream& in,Complex<T>& other); template <typename T> friend ostream & operator<<(ostream& out, const Complex<T>& other); private : T real, image; }; template <typename T> Complex <T> ::Complex() { } template <typename T> Complex <T> ::Complex(T real_n, T image_n) :real(real_n), image(image_n) { } template <typename T> Complex <T>::Complex(const Complex& other) { real = other.real; image = other.image; } template <typename T> Complex <T> Complex<T>::operator+(const Complex<T>& other) { return Complex<T>(real + other.real, image + other.image); } template <typename T> Complex <T>& Complex<T>::operator+=(const Complex<T>& other) { real += other.real; image += other.image; return *this ; } template <typename T> bool Complex<T>::operator==(const Complex<T>& other) const { if (real == other.real && image == other.image) return true ; else return false ; } template <typename T> T Complex <T>::get_real() const { return real; } template <typename T> T Complex <T>::get_imag()const { return image; } template <typename T> istream & operator>>(istream& in, Complex<T>& other) { in >> other.real >> other.image; return in ; } template <typename T> ostream & operator<<(ostream& out, const Complex<T>& other) { if(other.image<0 ) { T temp; temp = - other.image; out << other.real << " " <<"-"<< " " << temp << "i" ; } else { out << other.real << " " << "+" << " " << other.image << "i" ; } return out ; }
运行结果如下:


浙公网安备 33010602011771号