基类 Quote,定义图书的编号和价格
// Quote
class Quote {
public:
Quote() = default;
Quote(const string &book, double salesPrice) : bookNo(book), price(salesPrice) {}
// 拷贝/移动控制成员
Quote(const Quote &other) : bookNo(other.bookNo), price(other.price) {}
Quote(Quote &&other) : bookNo(std::move(other.bookNo)), price(std::move(other.price)) {}
Quote &operator=(const Quote &rhs);
Quote &operator=(Quote &&rhs);
string isbn() const { return bookNo; }
virtual double netPrice(std::size_t n) const { return n * price; } // 购买n本图书的花费
virtual ostream &debugPrint(ostream &os) const; // 打印成员信息
virtual ~Quote() = default;
private:
string bookNo; // 图书编号
protected:
double price = 0.0; // 价格,protected 访问类型标识派生类可以访问但是其他类不行
};
// 成员实现
ostream &Quote::debugPrint(ostream &os) const {
os << "ISBN: " << bookNo << ", price: " << price;
return os;
}
Quote &Quote::operator=(const Quote &rhs) {
if (this == &rhs) {
return *this;
}
bookNo = rhs.bookNo;
price = rhs.price;
return *this;
}
Quote &Quote::operator=(Quote &&rhs) {
if (this == &rhs) {
return *this;
}
bookNo = std::move(rhs.bookNo);
price = std::move(rhs.price);
return *this;
}
// 公共函数,打印给定图书购买n本的花费
// COMMON DEBUG_PRINT
double printTotal(ostream &os, Quote &item, std::size_t n) {
double ret = item.netPrice(n);
os << "ISBN: " << item.isbn() << " # sold: " << n << " total due: " << ret << endl;
return ret;
}
子类 DisQuote,折扣基类,定义折扣需要的数量和折扣优惠(优惠是超过数量或者小于数量等在派生类中根据业务确定)
// DisQuote 折扣基类,定义折扣需要的数量和折扣优惠(优惠是超过数量或者小于数量等在派生类中根据业务确定)
class DisQuote : public Quote {
public:
DisQuote() = default;
DisQuote(const string &book, double price, std::size_t qty, double disc) : Quote(book, price), quantity(qty),
discount(disc) {}
// 拷贝/移动控制成员
DisQuote(const DisQuote &other) : Quote(other), quantity(other.quantity), discount(other.discount) {}
DisQuote(DisQuote &&other) : Quote(std::move(other)), quantity(std::move(other.quantity)),
discount(std::move(other.discount)) {}
DisQuote &operator=(const DisQuote &rhs);
DisQuote &operator=(DisQuote &&rhs);
virtual double netPrice(std::size_t n) const = 0; // 纯虚函数
virtual ostream &debugPrint(ostream &os) const override; // 打印成员信息
protected:
std::size_t quantity = 0;
double discount = 0.0;
};
// 成员实现
ostream &DisQuote::debugPrint(ostream &os) const {
os << "ISBN: " << isbn() << ", price: " << price << ", quantity: " << quantity << ", discount: " << discount;
return os;
}
DisQuote &DisQuote::operator=(const DisQuote &rhs) {
if (this == &rhs) {
return *this;
}
Quote::operator=(rhs);
quantity = rhs.quantity;
discount = rhs.discount;
return *this;
}
DisQuote &DisQuote::operator=(DisQuote &&rhs) {
if (this == &rhs) {
return *this;
}
Quote::operator=(std::move(rhs));
quantity = std::move(rhs.quantity);
discount = std::move(rhs.discount);
return *this;
}
子类 BulkQuote ,大于给定数量才有折扣优惠,否则按照原价计算
// BulkQuote 大于给定数量才有折扣优惠,否则按照原件计算
class BulkQuote : public DisQuote {
public:
BulkQuote() = default;
// BulkQuote(const string &book, double price, std::size_t qty, double disc) : DisQuote(book, price, qty, disc) {}
using DisQuote::DisQuote; // "继承"直接基类的构造函数
// 拷贝/移动控制成员
BulkQuote(const BulkQuote &other) : DisQuote(other) { cout << "BulkQuote copy construct" << endl; }
BulkQuote(BulkQuote &&other) : DisQuote(std::move(other)) { cout << "BulkQuote move construct" << endl; }
BulkQuote &operator=(const BulkQuote &rhs);
BulkQuote &operator=(BulkQuote &&rhs);
virtual double netPrice(std::size_t n) const override;
virtual ostream &debugPrint(ostream &os) const override; // 打印成员信息
};
// 成员实现
double BulkQuote::netPrice(std::size_t n) const {
if (n >= quantity) {
return n * (1 - discount) * price;
} else {
return Quote::netPrice(n);
}
}
ostream &BulkQuote::debugPrint(ostream &os) const {
DisQuote::debugPrint(os);
return os;
}
BulkQuote &BulkQuote::operator=(const BulkQuote &rhs) {
cout << "BulkQuote copy assignment" << endl;
if (this == &rhs) {
return *this;
}
DisQuote::operator=(rhs);
return *this;
}
BulkQuote &BulkQuote::operator=(BulkQuote &&rhs) {
cout << "BulkQuote move assignment" << endl;
if (this == &rhs) {
return *this;
}
DisQuote::operator=(std::move(rhs));
return *this;
}
子类 SlightQuote, 小于给定数量的部分有折扣优惠,超过部分按照原价计算
// BulkQuote 小于给定数量的部分有折扣优惠,超过部分按照原件计算
class SlightQuote : public DisQuote {
public:
SlightQuote() = default;
// SlightQuote(const string &book, double price, std::size_t qty, double disc) : DisQuote(book, price, qty,
// disc) {}
using DisQuote::DisQuote; // "继承"直接基类的构造函数
// 拷贝/移动控制成员
SlightQuote(const SlightQuote &other) : DisQuote(other) { cout << "SlightQuote copy construct" << endl; }
SlightQuote(SlightQuote &&other) : DisQuote(std::move(other)) { cout << "SlightQuote move construct" << endl; }
SlightQuote &operator=(const SlightQuote &rhs);
SlightQuote &operator=(SlightQuote &&rhs);
virtual double netPrice(std::size_t n) const override;
virtual ostream &debugPrint(ostream &os) const override; // 打印成员信息
};
// 成员实现
double SlightQuote::netPrice(std::size_t n) const {
std::size_t exceedNum = n - quantity;
if (exceedNum < 0) {
return n * (1 - discount) * price;
} else {
// quantity * (1 - discount) * price + exceedNum * price;
return price * (n - quantity * discount);
}
}
ostream &SlightQuote::debugPrint(ostream &os) const {
DisQuote::debugPrint(os);
return os;
}
SlightQuote &SlightQuote::operator=(const SlightQuote &rhs) {
cout << "SlightQuote copy assignment" << endl;
if (this == &rhs) {
return *this;
}
DisQuote::operator=(rhs);
return *this;
}
SlightQuote &SlightQuote::operator=(SlightQuote &&rhs) {
cout << "SlightQuote move assignment" << endl;
if (this == &rhs) {
return *this;
}
DisQuote::operator=(std::move(rhs));
return *this;
}
测试代码:
// Quote测试
void MyQuoteTest() {
// Quote
MyQuoteSpace::Quote qt1("099-120-321", 20);
MyQuoteSpace::printTotal(cout, qt1, 20);
// BulkQuote
MyQuoteSpace::BulkQuote bqt1("099-120-321", 20, 10, 0.1);
MyQuoteSpace::BulkQuote bqt2("099-120-321", 20, 5, .19);
MyQuoteSpace::printTotal(cout, bqt1, 20);
MyQuoteSpace::printTotal(cout, bqt1, 10);
cout << endl;
MyQuoteSpace::Quote *pqt1 = &qt1, *pqt2 = &bqt1, *pqt3 = &bqt2;
pqt1->debugPrint(cout) << endl;
pqt2->debugPrint(cout) << endl;
pqt3->debugPrint(cout) << endl;
// SlightQuote
// MyQuoteSpace::DisQuote disquote; // 错误,不能定义抽象基类的对象
cout << endl;
MyQuoteSpace::Quote qt2("099-120-322", 40);
MyQuoteSpace::printTotal(cout, qt2, 20);
MyQuoteSpace::SlightQuote sqt1("099-120-322", 40, 10, 0.1);
MyQuoteSpace::SlightQuote sqt2("099-120-322", 40, 5, .19);
MyQuoteSpace::printTotal(cout, sqt1, 20);
MyQuoteSpace::printTotal(cout, sqt2, 4);
// 拷贝/移动控制测试
MyQuoteSpace::BulkQuote bqt3 = bqt1;
MyQuoteSpace::BulkQuote bqt4 = std::move(bqt3);
bqt4 = bqt1;
bqt4 = std::move(bqt2);
MyQuoteSpace::SlightQuote sqt3 = sqt1;
MyQuoteSpace::SlightQuote sqt4 = std::move(sqt3);
sqt4 = sqt1;
sqt4 = std::move(sqt2);
return;
}
调试结果
参考 C++ Primer 第五版 第15章