C++ Primer: Chapter 15 Object-Oriented Programming

Chapter 15 Object-Oriented Programming

Quote类

Quote.h

#ifndef MY_QUOTE_H
#define MY_QUOTE_H

#include<string>
#include<iostream>

using namespace std;

class Quote
{
public:
    Quote() = default;
    Quote(const std::string& book, double sales_price) :bookNo(book), price(sales_price) {};
    std::string isbn() const { return bookNo; };

    // copy control
    Quote(const Quote& rhs) : bookNo(rhs.bookNo), price(rhs.price) {  };
    Quote(Quote&&) = default;
    Quote& operator=(const Quote& rhs) { bookNo = rhs.bookNo; price = rhs.price; return *this; };
    Quote& operator=(Quote&&) = default;

    virtual double net_price(std::size_t n) const { return n * price; };
    //virtual void debug() const { cout << "Quote bookNo = " << bookNo << ", price = "<< price << endl; };
    virtual Quote* clone() const& { return new Quote(*this); }; //获得自身对象在动态内存的一个拷贝
    virtual Quote* clone()&& { return new Quote(std::move(*this)); }; //把自身对象移动到动态内存
    virtual ~Quote() = default;
    

private:
    std::string bookNo;
protected:
    double price = 0.0;
};

//非成员接口函数
double print_total(ostream&, const Quote&, size_t);

class Disc_quote : public Quote
{
public:
    Disc_quote() = default;
    Disc_quote(const std::string& book, double sales_price, std::size_t q, double d) : Quote(book, sales_price), min_qty(q), discount(d) {};
    double net_price(std::size_t) const override = 0;

protected:
    std::size_t min_qty = 0;
    double discount = 0.0;
};

class Bulk_quote : public Disc_quote
{
public:
    Bulk_quote() = default;
    // Bulk_quote(const std::string& book, double sales_price, std::size_t q, double d) :Disc_quote(book, sales_price, q, d) {};
    using Disc_quote::Disc_quote; // 与上面的定义相同
    double net_price(std::size_t n) const override;
    //void debug() const override { cout << "Bulk_quote min_qty = " << min_qty << ", discount = " << discount << endl; };
    virtual Quote* clone() const& override { return new Bulk_quote(*this); };
    virtual Quote* clone() && override { return new Bulk_quote(std::move(*this)); };

    // copy control
    Bulk_quote(const Bulk_quote& rhs) : Disc_quote(rhs) {};
    Bulk_quote(Bulk_quote&&) = default;
    Bulk_quote& operator=(const Bulk_quote& rhs) { (*this).Disc_quote::operator=(rhs);  return *this;};
    Bulk_quote& operator=(Bulk_quote&&) = default;
};

class limited_quote : public Disc_quote
{
public:
    limited_quote() = default;
    limited_quote(const std::string& book, double sales_price, std::size_t q, double d) :Disc_quote(book, sales_price, q, d) {};
    double net_price(std::size_t n) const override;
    //void debug() const override { cout << "limited_quote min_qty = " << min_qty << ", discount = " << discount << endl; }

};

#endif

Quote.cpp

#include"Quote.h"

double Bulk_quote::net_price(std::size_t cnt) const
{
	if (cnt >= min_qty)
		return cnt * (1 - discount) * price;
	else
		return cnt * price;
}

double limited_quote::net_price(std::size_t cnt) const
{
	if (cnt <= min_qty)
		return cnt * (1 - discount) * price;
	else
		return min_qty * (1 - discount) * price + (cnt - min_qty) * price;
}

double print_total(ostream& os, const Quote& item, size_t n)
{
	double ret = item.net_price(n);
	os << "ISBN: " << item.isbn() << " # sole: " << n << "total due: " << ret << endl;
	return ret;
}

Basket类

Basket.h

#include<memory>
#include<set>
#include<iostream>
#include"Quote.h"

using namespace std;

class Basket
{
public:
	//使用默认构造函数和拷贝控制成员

	void add_item(const Quote& sale) { items.insert(shared_ptr<Quote>(sale.clone())); };
	void add_item(Quote&& sale) { items.insert(shared_ptr<Quote>(std::move(sale).clone())); };
	double total_receipt(ostream&) const;

private:
	static bool compare(const shared_ptr<Quote> & lhs, const shared_ptr<Quote>& rhs)
	{
		return lhs->isbn() < rhs->isbn();
	}
	//一个multiset,按照compare规定的方法排序
	multiset<shared_ptr<Quote>, decltype(compare)*> items{ compare }; 
};

Basket.cpp

#include"Basket.h"

double Basket::total_receipt(ostream& os) const
{
	double sum = 0.0;
	for (auto iter = items.cbegin(); iter != items.cend(); iter = items.upper_bound(*iter))
		sum += print_total(os, **iter, items.count(*iter));
	os << "Total Sale: " << sum << endl;
	return sum;
}

TextQuery类

TextQuery.h

#include<vector>
#include<string>
#include<set>
#include<map>
#include<fstream>
#include<memory>

using namespace std;

class QueryResult;

class TextQuery
{
	friend class QueryResult;
public:
	using line_no = vector<string>::size_type;
	TextQuery(ifstream&);
	QueryResult query(const string& word) const;

private:
	shared_ptr<vector<string>> file;
	map<string, shared_ptr<set<line_no>>> wm;
};

class QueryResult
{
	friend ostream& print(ostream&, const QueryResult&);
public:
	using line_no = vector<string>::size_type;
	using line_it = set<line_no>::const_iterator;
	QueryResult(string s, shared_ptr<set<line_no>> p, shared_ptr<vector<string>> f) : sought(s), lines(p), file(f) {};
	line_it begin() const { return lines->begin(); };
	line_it end() const { return lines->end(); };
	shared_ptr<vector<string>> get_file() { return file; };
private:
	string sought;
	shared_ptr<set<line_no>> lines;
	shared_ptr<vector<string>> file;
};

class Query_base
{
	friend class Query;
protected:
	using line_no = TextQuery::line_no;
	virtual ~Query_base() = default;

private:
	//使用给定的TextQuery对象查找与之匹配的行
	virtual QueryResult eval(const TextQuery&) const = 0;
	//返回查询的string表示形式
	virtual string rep() const = 0;
};

class Query
{
	friend Query operator~(const Query&);
	friend Query operator|(const Query&, const Query&);
	friend Query operator&(const Query&, const Query&);
public:
	//Query接受string类型的构造函数
	Query(const string&);
	QueryResult eval(const TextQuery& t) const { return q->eval(t); };
	string rep() const { return q->rep(); };
private:
	//Query接受不同派生类型的Query_base对象的构造函数
	Query(shared_ptr<Query_base> query) : q(query) {};
	//被查询对象的指针
	shared_ptr<Query_base> q;
};

//ostream& operator<<(ostream& os, const Query& query)
//{
//	return os << query.rep();
//}

inline ostream& operator<<(ostream& os, const Query& query) {
	// Query::rep makes a virtual call through its Query_base pointer to rep()
	return os << query.rep();
}

class WordQuery : public Query_base
{
	friend class Query;
	WordQuery(const string& s) : query_word(s) {};
	QueryResult eval(const TextQuery& t) const { return t.query(query_word); };
	string rep() const { return query_word; };
	//要查询的单词
	string query_word;
};

//Query接受string的构造函数
inline Query::Query(const string& s) :q(new WordQuery(s)) {};

class NotQuery : public Query_base
{
	friend Query operator~(const Query&);
	NotQuery(const Query& q) : query(q) {};
	string rep() const { return "~(" + query.rep() + ")"; };
	QueryResult eval(const TextQuery&) const;
	Query query;
};

//Query接受NotQuery的构造函数
inline Query operator~(const Query& operand)
{
	//返回一个shared_ptr<Query_base>指针,相当于使用Query(shared_ptr<Query_base> query)隐式构建了Query对象
	return shared_ptr<Query_base>(new NotQuery(operand));
}

class BinaryQuery :public Query_base
{
protected:
	BinaryQuery(const Query& l, const Query& r, string s) :lhs(l), rhs(r), opSym(s) {};
	string rep() const { return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")"; };
	Query lhs, rhs;
	string opSym; //运算符的名字
};

class AndQuery : public BinaryQuery
{
	friend Query operator&(const Query&, const Query&);
	AndQuery(const Query& left, const Query& right) : BinaryQuery(left, right, "&") {};
	QueryResult eval(const TextQuery&) const;
};

inline Query operator&(const Query& lhs, const Query& rhs)
{
	return shared_ptr<Query_base>(new AndQuery(lhs, rhs));
}

class OrQuery : public BinaryQuery
{
	friend Query operator|(const Query&, const Query&);
	OrQuery(const Query& left, const Query right) :BinaryQuery(left, right, "|") {};
	QueryResult eval(const TextQuery&) const;
};

inline Query operator|(const Query& lhs, const Query& rhs)
{
	return shared_ptr<Query_base>(new OrQuery(lhs, rhs));
}

TextQuery.cpp

#include"TextQuery.h"
#include<sstream>
#include<algorithm>
#include<iostream>

TextQuery::TextQuery(ifstream& is) : file(new vector<string>)
{
	string text;
	while (getline(is, text))
	{
		file->push_back(text);
		size_t n = file->size() - 1;
		istringstream line(text);
		string word;
		while (line >> word)
		{
			shared_ptr<set<line_no>>& lines = wm[word]; //lines是指向set的智能指针
			if (!lines) //第一次遇到word时需要给lines分配一个新的内存空间
				lines.reset(new set<line_no>);
			lines->insert(n);
		}
	}
}

QueryResult TextQuery::query(const string& sought) const
{
	static shared_ptr<set<line_no>> nodata(new set<line_no>);
	auto loc = wm.find(sought);
	if (loc == wm.end())
		return QueryResult(sought, nodata, file); //未找到
	else
		return QueryResult(sought, loc->second, file);
}

ostream& print(ostream& os, const QueryResult& qr)
{
	os << qr.sought << " occurs " << qr.lines->size() << " " << ((qr.lines->size()) > 1 ? "times" : "time") << endl;
	for (auto num : *qr.lines)
		os << "\t(line " << num + 1 << ") " << *(qr.file->begin() + num) << endl;
	return os;
}

QueryResult OrQuery::eval(const TextQuery& text) const
{
	//返回right和left的QueryResult
	auto right = rhs.eval(text), left = lhs.eval(text);
	//将左侧运算结果的行号拷贝到set中
	auto ret_lines = make_shared<set<line_no>>(left.begin(), left.end());
	//插入右侧运算对象所得的行号
	ret_lines->insert(right.begin(), right.end());
	//返回一个新的QueryResult,用于表示lhs和rhs的并
	return QueryResult(rep(), ret_lines, left.get_file());
}

QueryResult AndQuery::eval(const TextQuery& text) const
{
	auto left = lhs.eval(text), right = rhs.eval(text);
	auto ret_lines = make_shared<set<line_no>>();
	set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin()));
	return QueryResult(rep(), ret_lines, left.get_file());
}

QueryResult NotQuery::eval(const TextQuery& text) const
{
	auto result = query.eval(text);
	auto ret_lines = make_shared<set<line_no>>();
	auto beg = result.begin(), end = result.end();
	auto sz = result.get_file()->size();
	for (size_t n = 0; n != sz; ++n)
	{
		if (beg == end || *beg != n)
			ret_lines->insert(n);
		else if (beg != end)
			++beg;
	}
	return QueryResult(rep(), ret_lines, result.get_file());
}

Homework

Test 15.3

class Quote
{
public:
    Quote() = default;
    Quote(const std::string& book, double sales_price) :bookNo(book), price(sales_price) {};
    std::string isbn() const { return bookNo; };

    virtual double net_price(std::size_t n) const { return n * price; };
    virtual ~Quote() = default;

private:
    std::string bookNo;
protected:
    double price = 0.0;
};
double print_total(ostream& os, const Quote& item, size_t n)
{
    double ret = item.net_price(n);
    os << "ISBN: " << item.isbn() << " # sole: " << n << "total due: " << ret << endl;
    return ret;
}

Test 15.5

class Quote
{
public:
    Quote() = default;
    Quote(const std::string& book, double sales_price) :bookNo(book), price(sales_price) {};
    std::string isbn() const { return bookNo; };

    virtual double net_price(std::size_t n) const { return n * price; };
    virtual ~Quote() = default;

private:
    std::string bookNo;
protected:
    double price = 0.0;
};

class Bulk_quote : public Quote
{
public:
    Bulk_quote() = default;
    Bulk_quote(const std::string& book, double sales_price, std::size_t q, double d) : Quote(book, sales_price), min_qty(q), discount(d) {};
    double net_price(std::size_t n) const override;
private:
    std::size_t min_qty = 0;
    double discount = 0.0;

};
double Bulk_quote::net_price(std::size_t cnt) const
{
	if (cnt >= min_qty)
		return cnt * (1 - discount) * price;
	else
		return cnt * price;
}

Test 15.6

int main()
{
    Quote q1("primer", 66.66);
    Bulk_quote q2("engine", 99.99, 2, 0.2);

    print_total(cout, q1, 4);
    print_total(cout, q2, 3);

    return 0;
}

Test 15.7

class limited_quote : public Quote
{
public:
    limited_quote() = default;
    limited_quote(const std::string& book, double sales_price, std::size_t q, double d) : Quote(book, sales_price), max_qty(q), discount(d) {};
    double net_price(std::size_t n) const override;
private:
    std::size_t max_qty = 0;
    double discount = 0.0;

};
double limited_quote::net_price(std::size_t cnt) const
{
	if (cnt <= max_qty)
		return cnt * (1 - discount) * price;
	else
		return max_qty * (1 - discount) * price + (cnt - max_qty) * price;
}
int main()
{
    Quote q1("primer", 66.66);
    Bulk_quote q2("engine", 66.66, 2, 0.2);
    limited_quote q3("render", 66.66, 3, 0.2);

    print_total(cout, q1, 4);
    print_total(cout, q2, 4);
    print_total(cout, q3, 4);

    return 0;
}

Test 15.11

class Quote
{
public:
    virtual void debug() const { cout << "Quote bookNo = " << bookNo << ", price = "<< price << endl; };
    

private:
    std::string bookNo;
protected:
    double price = 0.0;
};


class Bulk_quote : public Disc_quote
{
public:
    void debug() const override{ cout << "Bulk_quote min_qty = " << min_qty <<", discount = " << discount << endl; }
};

class limited_quote : public Disc_quote
{
public:
    void debug() const override { cout << "limited_quote min_qty = " << min_qty << ", discount = " << discount << endl; }

};

Test 15.15 & 15.16

class Quote
{
public:
    Quote() = default;
    Quote(const std::string& book, double sales_price) :bookNo(book), price(sales_price) {};
    std::string isbn() const { return bookNo; };

    virtual double net_price(std::size_t n) const { return n * price; };
    virtual void debug() const { cout << "Quote bookNo = " << bookNo << ", price = "<< price << endl; };
    virtual ~Quote() = default;
    

private:
    std::string bookNo;
protected:
    double price = 0.0;
};

class Disc_quote : public Quote
{
public:
    Disc_quote() = default;
    Disc_quote(const std::string& book, double sales_price, std::size_t q, double d) : Quote(book, sales_price), min_qty(q), discount(d) {};
    double net_price(std::size_t) const override = 0;

protected:
    std::size_t min_qty = 0;
    double discount = 0.0;
};

class Bulk_quote : public Disc_quote
{
public:
    Bulk_quote() = default;
    Bulk_quote(const std::string& book, double sales_price, std::size_t q, double d) :Disc_quote(book, sales_price, q, d) {};
    double net_price(std::size_t n) const override;
    void debug() const override{ cout << "Bulk_quote min_qty = " << min_qty <<", discount = " << discount << endl; }
};

class limited_quote : public Disc_quote
{
public:
    limited_quote() = default;
    limited_quote(const std::string& book, double sales_price, std::size_t q, double d) :Disc_quote(book, sales_price, q, d) {};
    double net_price(std::size_t n) const override;
    void debug() const override { cout << "limited_quote min_qty = " << min_qty << ", discount = " << discount << endl; }

};

Test 15.17

不允许使用抽象类类型的对象

Test 15.19

class Base
{
public:
    void pub_mem();
protected:
    int prot_mem;
private:
    char priv_mem;
};

struct Pub_Derv : public Base
{
    void memfunc(Base& b) { b = *this; };
    
};

struct Priv_Derv : private Base
{
    void memfunc(Base& b) { b = *this; };
};

struct Prot_Derv : protected Base
{
    void memfunc(Base& b) { b = *this; };
};

struct Derived_from_Public : public Pub_Derv
{
    void memfunc(Base& b) { b = *this; };
};

struct Derived_from_Private : public Priv_Derv
{
    void memfunc(Base& b) { b = *this; };
};

struct Derived_from_Protected : public Prot_Derv
{
    void memfunc(Base& b) { b = *this; };
};

int main()
{
    Pub_Derv d1;
    Priv_Derv d2;
    Prot_Derv d3;
    Derived_from_Public d4;
    Derived_from_Private d5;
    Derived_from_Protected d6;

    Base* p = &d1;
    p = &d2;
    p = &d3;
    p = &d4;
    p = &d5;
    p = &d6
    

    return 0;
}

Test 15.21

考察数据抽象能力,Shape类参考自第 15 章 (houhaibushihai.me)

tatic const float PI = 3.14159f;

class Shape {
public:
    virtual const char* shape_name() = 0;
    virtual void resize_by_percentage(float pct) = 0;
    virtual ~Shape() { };
};

class Shape_2D : public Shape {
public:
    Shape_2D() = default;
    Shape_2D(float x, float y) : x_(x), y_(y) { }

    virtual float area() const = 0;             // 面积
    virtual float diameter() const = 0;         // 直径
    virtual float circumference() const = 0;    // 周长

    ~Shape_2D() override { }

private:
    float x_ = 0.f;
    float y_ = 0.f;
};

class Shape_3D : public Shape {
public:
    Shape_3D() = default;
    Shape_3D(float x, float y, float z) : x_(x), y_(y), z_(z) { }

    virtual float volume() const = 0;           // 体积

    ~Shape_3D() override { }

protected:
    float x_ = 0.f;
    float y_ = 0.f;
    float z_ = 0.f;
};

class Box : public Shape_3D {
public:
    Box() = default;
    explicit Box(float width) : half_len_x_(width * 0.5f),
        half_len_y_(width * 0.5f), half_len_z_(width * 0.5f) { }
    Box(float center_x, float center_y, float center_z,
        float len_x, float len_y, float len_z) :
        Shape_3D(center_x, center_y, center_z),
        half_len_x_(len_x * 0.5f), half_len_y_(len_y * 0.5f),
        half_len_z_(len_z * 0.5f) { }

    const char* shape_name() override { return "Box"; }
    void resize_by_percentage(float pct) override {
        half_len_x_ *= pct;
        half_len_y_ *= pct;
        half_len_z_ *= pct;
    }

    float volume() const override {
        return half_len_x_ * half_len_y_ * half_len_z_ * 8;
    }

    ~Box() override { }

private:
    float half_len_x_ = 0.5f;
    float half_len_y_ = 0.5f;
    float half_len_z_ = 0.5f;
};

class Circle : public Shape_2D {
public:
    Circle() = default;
    explicit Circle(float radius) : radius_(radius) { }
    Circle(float center_x, float center_y, float radius) :
        Shape_2D(center_x, center_y), radius_(radius) { }

    float area() const override {
        return PI * radius_ * radius_;
    }
    float diameter() const override {
        return 2 * radius_;
    }
    float circumference() const override {
        return 2 * PI * radius_;
    }

    const char* shape_name() override { return "Circle"; }
    void resize_by_percentage(float pct) override { radius_ *= pct; }

    ~Circle() override { };

protected:
    float radius_ = 1.f;            // 半径
};

class Sphere : public Shape_3D {
public:
    Sphere() = default;
    explicit Sphere(float radius) : radius_(radius) { }
    Sphere(float center_x, float center_y, float center_z, float radius)
        : Shape_3D(center_x, center_y, center_z), radius_(radius) { }

    const char* shape_name() override { return "Sphere"; }
    void resize_by_percentage(float pct) override { radius_ *= pct; }

    float volume() const override {
        return 4 * PI * radius_ * radius_ * radius_ / 3;
    }

    ~Sphere() override { }

protected:
    float radius_ = 1.f;            // 球体半径
};

class Cone : public Shape_3D {
public:
    Cone() = default;
    Cone(float radius, float height) : radius_(radius), height_(height) { }
    Cone(float center_x, float center_y, float center_z, float radius,
        float height) : Shape_3D(center_x, center_y, center_z),
        radius_(radius), height_(height) { }

    const char* shape_name() override { return "Cone"; }
    void resize_by_percentage(float pct) override {
        radius_ *= pct;
        height_ *= pct;
    }

    float volume() const override {
        return PI * radius_ * radius_ * height_ / 3;
    }

    ~Cone() override { }

protected:
    float radius_ = 1.f;            // 圆锥体底面圆半径
    float height_ = 1.f;            // 圆锥体高
};

Test 15.26

using namespace std;

class Quote
{
public:

    // copy control
    Quote(const Quote& rhs) : bookNo(rhs.bookNo), price(rhs.price) { cout << "do Quote copy" << endl; };
    Quote(Quote&&) = default;
    Quote& operator=(const Quote& rhs) { bookNo = rhs.bookNo; price = rhs.price; cout << "do Quote '='" << endl; return *this; };
    Quote& operator=(Quote&&) = default;

private:
    std::string bookNo;
protected:
    double price = 0.0;
};

class Disc_quote : public Quote
{
	//.....
};

class Bulk_quote : public Disc_quote
{
public:
    // copy control
    Bulk_quote(const Bulk_quote& rhs) : Disc_quote(rhs) {cout << "do Bulk_quote copy" << endl;};
    Bulk_quote(Bulk_quote&&) = default;
    Bulk_quote& operator=(const Bulk_quote& rhs) { (*this).Disc_quote::operator=(rhs); cout << "do Bulk_quote '='" << endl; return *this;};
    Bulk_quote& operator=(Bulk_quote&&) = default;
};

Test 15.27

class Bulk_quote : public Disc_quote
{
public:
    Bulk_quote() = default;
    // Bulk_quote(const std::string& book, double sales_price, std::size_t q, double d) :Disc_quote(book, sales_price, q, d) {};
    using Disc_quote::Disc_quote; // 与上面的定义相同

};

Test 15.28

int main()
{

    vector<Quote> vec;
    vec.push_back(Bulk_quote("book1", 30, 2, 0.2));
    vec.push_back(Bulk_quote("book2", 40, 2, 0.2));
    vec.push_back(Bulk_quote("book3", 50, 2, 0.2));

    double sum = 0;
    for (auto& i: vec)
        sum += i.net_price(4);

    cout << sum << endl;
    return 0;
}

这个程序不符合设计意图,添加进vec的Bulk_quote对象被强制转化成了Quote对象,派生类部分(折扣相关的成员)被忽略掉

Test 15.29

int main()
{

    vector<shared_ptr<Quote>> vec;
    vec.push_back(make_shared<Bulk_quote>("book1", 30, 2, 0.2));
    vec.push_back(make_shared<Bulk_quote>("book2", 40, 2, 0.2));
    vec.push_back(make_shared<Bulk_quote>("book3", 50, 2, 0.2));

    double sum = 0;
    for (auto& i: vec)
        sum += i->net_price(4);

    cout << sum << endl;
    return 0;
}

Test 15.30

Quote.h 更新

class Quote
{
    virtual Quote* clone() const& { return new Quote(*this); }; //获得自身对象在动态内存的一个拷贝
    virtual Quote* clone()&& { return new Quote(std::move(*this)); }; //把自身对象移动到动态内存
    virtual ~Quote() = default;
};

//非成员接口函数
double print_total(ostream&, const Quote&, size_t);

class Bulk_quote : public Disc_quote
{
public:
    virtual Quote* clone() const& override { return new Bulk_quote(*this); };
    virtual Quote* clone() && override { return new Bulk_quote(std::move(*this)); };

};

Basket.h

class Basket
{
public:
	//使用默认构造函数和拷贝控制成员

	void add_item(const Quote& sale) { items.insert(shared_ptr<Quote>(sale.clone())); };
	void add_item(Quote&& sale) { items.insert(shared_ptr<Quote>(std::move(sale).clone())); };
	double total_receipt(ostream&) const;

private:
	static bool compare(const shared_ptr<Quote> & lhs, const shared_ptr<Quote>& rhs)
	{
		return lhs->isbn() < rhs->isbn();
	}
	//一个multiset,按照compare规定的方法排序
	multiset<shared_ptr<Quote>, decltype(compare)*> items{ compare }; 
};

Basket.cpp

double Basket::total_receipt(ostream& os) const
{
	double sum = 0.0;
	for (auto iter = items.cbegin(); iter != items.cend(); iter = items.upper_bound(*iter))
		sum += print_total(os, **iter, items.count(*iter));
	os << "Total Sale: " << sum << endl;
	return sum;
}

main.cpp

int main()
{
    Basket basket;
    Bulk_quote b1("book1", 30, 2, 0.2);
    Bulk_quote b2("book2", 40, 4, 0.2);
    Bulk_quote b3("book3", 50, 1, 0.2);
    basket.add_item(b1);
    basket.add_item(b1);
    basket.add_item(b1);
    basket.add_item(b2);
    basket.add_item(b3);
    basket.add_item(b2);

    basket.total_receipt(cout);


    return 0;
}

Test 15.31

(a): WordQuery -> NotQuery -> AndQuery -> OrQuery
(b): WordQuery -> NotQuery -> AndQuery -> OrQuery (same as the previous one)
(c): WordQuery -> AndQuery -> OrQuery
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值