C++ Primer 学习笔记 第十四章 重载运算与类型转换
494 重载sales_data的输出运算符
#include <string>
#include <iostream>
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;
return 0;
}
成员函数版本的重载<< 不推荐
#include <string>
#include <iostream>
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;
return 0;
}
495 重载输入运算符
#include <string>
#include <iostream>
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;
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 <string>
#include <iostream>
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;
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 <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
using namespace std;
class StrBlob{
public:
friend class StrBlobPtr;
StrBlobPtr begin();
StrBlobPtr end();
typedef std::vector<std::string>::size_type size_type;
StrBlob();
StrBlob(std::initializer_list<std::string> 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<std::vector<std::string>> data;
private:
void check(size_type i, const std::string &msg) const;
};
StrBlob::StrBlob() :data(make_shared<vector<string>>()){}
StrBlob::StrBlob(initializer_list<string> il):data(make_shared<vector<string>>(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();
StrBlobPtr operator++();
StrBlobPtr operator++(int);
private:
shared_ptr<vector<string>> check(size_t, const string&) const;
weak_ptr<vector<string>> wptr;
size_t curr;
};
shared_ptr<vector<string>> 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<string> 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 <<stbr.deref() << endl;
stbr.incr();
} catch (...) {
cout << "end of data" << endl;
break;
}
}
return 0;
}
504 重写解引用运算符
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
using namespace std;
class StrBlob{
public:
friend class StrBlobPtr;
StrBlobPtr begin();
StrBlobPtr end();
typedef std::vector<std::string>::size_type size_type;
StrBlob();
StrBlob(std::initializer_list<std::string> 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<std::vector<std::string>> data;
private:
void check(size_type i, const std::string &msg) const;
};
StrBlob::StrBlob() :data(make_shared<vector<string>>()){}
StrBlob::StrBlob(initializer_list<string> il):data(make_shared<vector<string>>(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();
StrBlobPtr operator++();
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<vector<string>> check(size_t, const string&) const;
weak_ptr<vector<string>> wptr;
size_t curr;
};
shared_ptr<vector<string>> 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;
cout << *(++p) << endl;
return 0;
}
506 重写调用运算符
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
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 <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
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);
cout << endl;
PrintString errors(cerr, '\n');
errors(s);
cout << endl;
vector<string> vs = {"a", "b", "c"};
for_each(vs.begin(), vs.end(), errors);
return 0;
}
508 类对象和lambda函数的互换
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
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<string> words = {"a", "abcd", "ab", "abc"};
stable_sort(words.begin(), words.end(), ShorterString());
ostream_iterator<string> out_iter(cout, " ");
copy(words.begin(), words.end(), out_iter);
return 0;
}
508 类对象代替lambda捕获参数
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
using namespace std;
void elimDups(vector<string> &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<string> &words, vector<string>::size_type sz){
elimDups(words);
stable_sort(words.begin(), words.end(), [](const string &a, const string &b){return a.size()<b.size();});
for (auto val:words){
cout << val << " ";
}
cout << endl;
auto wc = find_if(words.begin(), words.end(), SizeComp(sz));
auto count = words.end() - wc;
cout << count << endl;
for_each(wc, words.end(),[](const string &s){cout << s << " ";});
cout << endl;
}
int main() {
vector<string> vec= {"the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"};
biggies(vec, 4);
}
510 使用标准库函数对象
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
using namespace std;
bool compare(const int *a, const int *b){
return *a < *b;
}
int main() {
plus<int> intAdd;
negate<int>intNegate;
int sum = intAdd(10, 20);
cout << sum << endl;
sum = intNegate(intAdd(10, 20));
cout << sum << endl;
vector<int> nums = {1, 3, 2, 6, 5, 4};
vector<int *> p_nums;
for (auto iter=nums.begin(); iter!=nums.end(); ++iter){
p_nums.push_back(&*iter);
}
sort(p_nums.begin(), p_nums.end(), compare);
for (auto iter=p_nums.begin(); iter!=p_nums.end(); ++iter){
cout << **iter << " ";
}
cout << endl;
}
512 可调用对象与function
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;
int add(int a, int b){
return a+b;
}
class divide{
public:
int operator()(int a, int b){return a/b;};
};
int main() {
function<int(int, int)> f1 = add;
function<int(int, int)> f2 = divide();
function<int(int, int)> f3 = [](int i, int j){return i*j;};
cout << f1(4, 2) << endl;
cout << f2(4, 2) << endl;
cout << f3(4, 2) << endl;
}
513 function结合map构造计算器
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;
int add(int a, int b){
return a+b;
}
class divide{
public:
int operator()(int a, int b){return a/b;};
};
auto mod = [](int i, int j){return i%j;};
int main() {
map<string, function<int(int, int)>> binops ={
{"+", add},
{"-", minus<int>()},
{"/", divide()},
{"*", [](int i, int j){return i*j;}},
};
cout<< binops["+"](10, 5) << endl;
}
514 类型转换运算符
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;
class SmallInt{
public:
SmallInt(int i=0, int j=0):val(i){
if(i<0||i>255){
throw out_of_range("Bad SmallInt value");
}
}
operator int() const{return val;};
size_t val;
};
int main() {
SmallInt si;
si = 4;
cout << si.val << endl;
cout << si+3 << endl;
si = 3.14;
cout << si.val << endl;
cout << si+3.14 << endl;
}
516 类类型显式转换运算符
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;
class SmallInt{
friend ostream& operator<<(ostream &, const SmallInt &);
public:
SmallInt(int n=0):val(n){}
explicit operator int() const{
return val;
}
private:
size_t val;
};
ostream& operator<<(ostream &os, const SmallInt &item){
os << item.val;
return os;
}
int main() {
SmallInt si;
si = 4;
cout << si << endl;
cout << static_cast<int>(si) + 3 << endl;
}
14.47 类方法两个不同的const的区别
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;
struct Integral{
Integral(int n=0):val(n){
}
operator const int(){
cout << "operator const int()" << endl;
val = 6;
return val;
};
operator int() const{
cout << "operator int() const" << endl;
return 4;
};
int val;
};
int main() {
Integral itg;
const Integral itg2;
itg = 3;
int i = itg;
int j = itg2;
}
520 避免二义性
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;
struct C{
C(int){};
};
struct D{
D(int){};
};
void manip(const C&){
}
void manip(const D&){
}
int main() {
manip(10);
manip(C(10));
}
14.51
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;
struct LongDouble{
LongDouble(double = 0.0){cout << "constructor" << endl;};
operator double(){return 2;};
operator float(){return 4;};
};
void calc(int){};
void calc(LongDouble){};
int main() {
LongDouble ldObj;
float ex2 = ldObj;
double dval=5;
calc(dval);
}
522 算术类型转换和重载运算符的二义性
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <iterator>
#include <memory>
#include <fstream>
#include <algorithm>
#include <functional>
#include <map>
using namespace std;
class SmallInt{
friend SmallInt operator+(const SmallInt&, const SmallInt&);
public:
SmallInt(int n =0):val(n){};
operator int() const{return val;}
size_t val;
};
SmallInt operator+(const SmallInt& a, const SmallInt& b){
SmallInt res;
res.val = a.val + b.val;
return res;
}
int main() {
SmallInt s1(1), s2(2);
SmallInt s3 = s1 + s2;
cout << s3.val << endl;
}