C++ Primer 学习笔记 第十四章 重载运算与类型转换 494 重载sales_data的输出运算符
#include #include using namespace std;class Sales_data { friend ostream &operator<<(ostream &, const Sales_data &item);public: Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ } Sales_data() : Sales_data("", 0, 0.0f){ } std::string isbn() const { return bookNo; }private: inline double avg_price() const; std::string bookNo; unsigned units_sold = 0; double revenue = 0.0;};inline double Sales_data::avg_price() const{ return units_sold ? revenue/units_sold : 0;}ostream &operator<<(ostream &os, const Sales_data &item){ os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price(); return os;}int main(){ Sales_data data("abc", 2, 4); cout << data << endl;// abc 2 8 4 return 0;}
成员函数版本的重载<< 不推荐
#include #include using namespace std;class Sales_data {public: Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ } Sales_data() : Sales_data("", 0, 0.0f){ } std::string isbn() const { return bookNo; } ostream &operator<<(ostream&);private: inline double avg_price() const; std::string bookNo; unsigned units_sold = 0; double revenue = 0.0;};inline double Sales_data::avg_price() const{ return units_sold ? revenue/units_sold : 0;}ostream & Sales_data::operator<<(ostream &os) { os << this->isbn() << " " << this->units_sold << " " << this->revenue << " " << this->avg_price(); return os;}int main(){ Sales_data data("abc", 2, 4); data << cout; // abc 2 8 4 return 0;}
495 重载输入运算符
#include #include using namespace std;class Sales_data { friend ostream &operator<<(ostream &, Sales_data&); friend istream &operator>>(istream &, Sales_data &);public: Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ } Sales_data() : Sales_data("", 0, 0.0f){ } std::string isbn() const { return bookNo; }private: inline double avg_price() const; std::string bookNo; unsigned units_sold = 0; double revenue = 0.0;};inline double Sales_data::avg_price() const{ return units_sold ? revenue/units_sold : 0;}ostream &operator<<(ostream &os, Sales_data& data){ os << data.bookNo << " " << data.units_sold << " " << data.revenue << " " << data.avg_price(); return os;}istream &operator>>(istream &is, Sales_data &item){ double price; is >> item.bookNo >> item.units_sold >> price; if (is) item.revenue = item.units_sold*price; else item = Sales_data(); return is;}int main(){ Sales_data data("abc", 2, 4); cout << data << endl; // abc 2 8 4 cout << "please enter bookNo, units_sold, price: " << endl; cin >> data; cout << data; return 0;}
497 重写+=和+
Sales_data& Sales_data::operator+=(const Sales_data &rhs) { units_sold += rhs.units_sold; revenue += rhs.revenue; return *this;}Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs){ Sales_data sum = lhs; sum += rhs; return sum;}
499 运算符重写综合实例
#include #include using namespace std;class Sales_data { friend ostream &operator<<(ostream &, Sales_data&); friend istream &operator>>(istream &, Sales_data &); friend bool operator==(const Sales_data&, const Sales_data&); friend bool operator!=(const Sales_data&, const Sales_data&);public: Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(n*p){ } Sales_data() : Sales_data("", 0, 0.0f){ } std::string isbn() const { return bookNo; } Sales_data& operator+=(const Sales_data &rhs);private: inline double avg_price() const; std::string bookNo; unsigned units_sold = 0; double revenue = 0.0;};inline double Sales_data::avg_price() const{ return units_sold ? revenue/units_sold : 0;}ostream &operator<<(ostream &os, Sales_data& data){ os << data.bookNo << " " << data.units_sold << " " << data.revenue << " " << data.avg_price(); return os;}istream &operator>>(istream &is, Sales_data &item){ double price; is >> item.bookNo >> item.units_sold >> price; item.revenue = item.units_sold*price; return is;}Sales_data& Sales_data::operator+=(const Sales_data &rhs) { units_sold += rhs.units_sold; revenue += rhs.revenue; return *this;}Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs){ Sales_data sum = lhs; sum += rhs; return sum;}bool operator==(const Sales_data& lhs, const Sales_data& rhs){ return lhs.isbn()==rhs.isbn() && lhs.units_sold==rhs.units_sold && lhs.revenue==rhs.revenue;}bool operator!=(const Sales_data &lhs, const Sales_data &rhs){ return !(lhs==rhs);}int main(){ Sales_data data("abc", 2, 4); cout << data << endl; // abc 2 8 4// cout << "please enter bookNo, units_sold, price: " << endl;// cin >> data;// cout << data; Sales_data data2("efg", 3, 5); Sales_data data3 = data + data2; cout << data3; return 0;}
501 下标运算符
string& operator[](size_t n){return elements[n];}; const string& operator[](size_t n) const{return elements[n];};
503 前置和后置版本的++
#include #include #include #include #include #include #include using namespace std;class StrBlob{public: friend class StrBlobPtr; StrBlobPtr begin(); StrBlobPtr end(); typedef std::vector::size_type size_type; StrBlob(); StrBlob(std::initializer_list il); size_type size() const {return data->size();}; bool empty() const {return data->empty();}; void push_back(const std::string &t){data->push_back(t);}; void pop_back(); std::string& front(); std::string& back(); std::shared_ptr> data;private: void check(size_type i, const std::string &msg) const;};StrBlob::StrBlob() :data(make_shared>()){}StrBlob::StrBlob(initializer_list il):data(make_shared>(il)){}void StrBlob::check(size_type i, const std::string &msg) const { if (i>=data->size()) throw out_of_range(msg);}string& StrBlob::front() { check(0, "front on empty StrBlob"); return data->front();}string& StrBlob::back() { check(0, "back on empty StrBlob"); return data->back();}void StrBlob::pop_back() { check(0, "pop_back on empty StrBlob"); data->pop_back();}class StrBlobPtr{public: StrBlobPtr():curr(0){} StrBlobPtr(StrBlob &a, size_t sz=0):wptr(a.data), curr(sz){} string& deref() const; StrBlobPtr& incr(); // front ++ StrBlobPtr operator++(); // back ++ StrBlobPtr operator++(int);private: shared_ptr> check(size_t, const string&) const; weak_ptr> wptr; size_t curr;};//shared_ptr>;shared_ptr> StrBlobPtr::check(size_t i, const string &msg) const { auto ret = wptr.lock(); if (!ret){ throw runtime_error("unbound StrBlobPtr"); } if (i>=ret->size()) throw out_of_range(msg); return ret;}string& StrBlobPtr::deref() const { auto p = check(curr, "dereference past end"); return (*p)[curr];}StrBlobPtr& StrBlobPtr::incr() { check(curr, "increment past end of StrBlobPtr"); ++curr; return *this;}StrBlobPtr StrBlob::begin(){ return StrBlobPtr(*this);}StrBlobPtr StrBlob::end(){ return StrBlobPtr(*this, data->size());}StrBlobPtr StrBlobPtr::operator++() { check(curr, "increment past end ofStrBlobPtr"); ++curr; return *this;}StrBlobPtr StrBlobPtr::operator++(int) { StrBlobPtr ret = *this; ++*this; return ret;}int main() { StrBlob stb; StrBlobPtr stbr(stb); vector vec = {"a", "b", "c"}; for (string text:vec){ stb.push_back(text); } auto begin = stb.begin(); auto end = stb.end(); stbr++; ++stbr; while(true){ try{ cout <
504 重写解引用运算符
#include #include #include #include #include #include #include using namespace std;class StrBlob{public: friend class StrBlobPtr; StrBlobPtr begin(); StrBlobPtr end(); typedef std::vector::size_type size_type; StrBlob(); StrBlob(std::initializer_list il); size_type size() const {return data->size();}; bool empty() const {return data->empty();}; void push_back(const std::string &t){data->push_back(t);}; void pop_back(); std::string& front(); std::string& back(); std::shared_ptr> data;private: void check(size_type i, const std::string &msg) const;};StrBlob::StrBlob() :data(make_shared>()){}StrBlob::StrBlob(initializer_list il):data(make_shared>(il)){}void StrBlob::check(size_type i, const std::string &msg) const { if (i>=data->size()) throw out_of_range(msg);}string& StrBlob::front() { check(0, "front on empty StrBlob"); return data->front();}string& StrBlob::back() { check(0, "back on empty StrBlob"); return data->back();}void StrBlob::pop_back() { check(0, "pop_back on empty StrBlob"); data->pop_back();}class StrBlobPtr{public: StrBlobPtr():curr(0){} StrBlobPtr(StrBlob &a, size_t sz=0):wptr(a.data), curr(sz){} string& deref() const; StrBlobPtr& incr(); // front ++ StrBlobPtr operator++(); // back ++ StrBlobPtr operator++(int); StrBlobPtr operator--(); string& operator*() const{ auto p = check(curr, "dereference past end"); cout << "curr: " << curr << endl; return (*p)[curr]; }private: shared_ptr> check(size_t, const string&) const; weak_ptr> wptr; size_t curr;};//shared_ptr>;shared_ptr> StrBlobPtr::check(size_t i, const string &msg) const { auto ret = wptr.lock(); if (!ret){ throw runtime_error("unbound StrBlobPtr"); } if (i>=ret->size()) throw out_of_range(msg); return ret;}string& StrBlobPtr::deref() const { auto p = check(curr, "dereference past end"); return (*p)[curr];}StrBlobPtr& StrBlobPtr::incr() { check(curr, "increment past end of StrBlobPtr"); ++curr; return *this;}StrBlobPtr StrBlob::begin(){ return StrBlobPtr(*this);}StrBlobPtr StrBlob::end(){ return StrBlobPtr(*this, data->size());}StrBlobPtr StrBlobPtr::operator++() { check(curr, "increment past end ofStrBlobPtr"); ++curr; return *this;}StrBlobPtr StrBlobPtr::operator++(int) { StrBlobPtr ret = *this; ++*this; return ret;}StrBlobPtr StrBlobPtr::operator--() { check(curr, "increment past end ofStrBlobPtr"); --curr; return *this;}int main() { StrBlob a1 = {"hi", "bye", "now"}; StrBlobPtr p(a1); *p = "okay"; cout << *p << endl; // okay cout << *(++p) << endl; // bye return 0;}
506 重写调用运算符
#include #include #include #include #include #include #include using namespace std;struct absInt{ int operator() (int val) const { return val < 0 ? -val:val; }};int main() { int i = -42; absInt absObj; cout << absObj(i) << endl; return 0;}
507 重载运算符和for_each结合使用
#include #include #include #include #include #include #include #include using namespace std;class PrintString{public: PrintString(ostream &o=cout, char c=' '):os(o),sep(c){} void operator()(const string &s) const{os << s << sep;}private: ostream &os; char sep;};int main() { PrintString printer; string s = "hello world"; printer(s); // hello world cout << endl; PrintString errors(cerr, 'n'); errors(s); // hellowordn cout << endl; vector vs = {"a", "b", "c"}; for_each(vs.begin(), vs.end(), errors); return 0;}
508 类对象和lambda函数的互换
#include #include #include #include #include #include #include #include using namespace std;class ShorterString{public: bool operator()(const string &s1, const string &s2) const { return s1.size() < s2.size(); }};bool compare(const string &s1, const string &s2){ return s1.size() < s2.size();}int main() { vector words = {"a", "abcd", "ab", "abc"};// stable_sort(words.begin(), words.end(),// [](const string &a, const string &b){return a.size() out_iter(cout, " "); copy(words.begin(), words.end(), out_iter); return 0;}
508 类对象代替lambda捕获参数
#include #include #include #include #include #include #include #include using namespace std;void elimDups(vector &words){ sort(words.begin(), words.end()); auto unqi = unique(words.begin(), words.end()); words.erase(unqi, words.end());}class SizeComp{public: SizeComp(size_t n):sz(n){} bool operator()(const string &s) const{ return s.size() >= sz; }private: size_t sz;};void biggies(vector &words, vector::size_type sz){ elimDups(words); stable_sort(words.begin(), words.end(), [](const string &a, const string &b){return a.size()=sz;}); auto wc = find_if(words.begin(), words.end(), SizeComp(sz)); auto count = words.end() - wc; cout << count << endl; // 5 5 elements with length >=4 for_each(wc, words.end(),[](const string &s){cout << s << " ";}); cout << endl; // over slow jumps quick turtle}int main() { vector vec= {"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"}; biggies(vec, 4);}
510 使用标准库函数对象
#include #include #include #include #include #include #include #include #include using namespace std;bool compare(const int *a, const int *b){ return *a < *b;}int main() { plus intAdd; negateintNegate; int sum = intAdd(10, 20); cout << sum << endl; // 30 sum = intNegate(intAdd(10, 20)); cout << sum << endl; // -30 vector nums = {1, 3, 2, 6, 5, 4}; vector p_nums; for (auto iter=nums.begin(); iter!=nums.end(); ++iter){ p_nums.push_back(&*iter); }// sort(p_nums.begin(), p_nums.end(), [](string *a, string *b){return (*a)<(*b);});// sort(p_nums.begin(), p_nums.end(), less()); sort(p_nums.begin(), p_nums.end(), compare); for (auto iter=p_nums.begin(); iter!=p_nums.end(); ++iter){ cout << **iter << " "; } cout << endl; // 1 2 3 4 5 6}
512 可调用对象与function
#include #include #include #include #include #include #include #include #include #include
513 function结合map构造计算器
#include #include #include #include #include #include #include #include #include #include
514 类型转换运算符
#include #include #include #include #include #include #include #include #include #include
516 类类型显式转换运算符
#include #include #include #include #include #include #include #include #include #include
14.47 类方法两个不同的const的区别
#include #include #include #include #include #include #include #include #include #include
520 避免二义性
#include #include #include #include #include #include #include #include #include #include
14.51
#include #include #include #include #include #include #include #include #include #include
522 算术类型转换和重载运算符的二义性
#include #include #include #include #include #include #include #include #include #include